启动领域驱动设计的最佳方式是什么
建议的资源是什么
编辑:
我的意思是,我想知道如何开始学习DDD(就像通过阅读开始TDD一样) 有一本关于域驱动设计的大书,经过精辟删节,可在此处免费下载:
要开始“做”领域驱动的设计,您只需要遵循本书中的要点。与企业共享一种语言,创建代表企业可以识别的事物的对象,等等
要全面开发现有的大型应用程序(但并非不可能),难度更大,但如果您正在编写新的内容,这将是一个100%投入开发的绝佳机会。关于DDD的权威书籍是
然而,这本书需要一些酝酿,最好是通过实践和观察经
我刚才打这个问题的时候就想到了。但我认为这并不能回答我的问题
我一直在与.NETMVC3合作,希望有一个贫血模型。视图模型和编辑模型最好作为哑数据容器,您可以将其从控制器传递到视图。任何类型的应用程序流都应该来自控制器,视图处理UI问题。在MVC中,我们不希望模型中出现任何行为
但是,我们也不希望控制器中有任何业务逻辑。对于较大的应用程序,最好将域代码与模型、视图和控制器(以及HTTP)分开并独立于它们。因此,有一个单独的项目,它首先提供一个域模型(带有实体和值对象,根据DDD组合成聚合)
我已
当您以OO/DDD风格开发架构并对某些领域实体(如订单实体)建模时,您将把与订单相关的整个逻辑放入订单实体中。
但当应用程序变得更加复杂时,Order entity收集了越来越多的逻辑,这个类变得非常庞大。
与贫血模型相比,是的,这显然是一种反模式,但所有这些巨大的逻辑在不同的服务中是分离的
处理大型域实体可以吗?或者我理解有什么错误?在DDD中使用服务也可以。您通常会在域、应用程序或基础架构层看到服务
Eric在他的书中使用这些指导原则来确定何时使用服务:
该操作涉及的域概念不是实体或值对象
我正在讨论分布式域驱动设计背后的一些概念,我正在构建一个概念证明。我有三个C#解决方案,它们在整个系统中具有特定的责任
我的解决办法是:
写入模型(从客户端接收命令并创建和发送事件)
读取模型(从写入模型接收事件、创建数据库并向客户端公开DTO服务,可能是两个独立的解决方案)
客户端(调用服务以获取所需的数据,并向写模型发送命令)
这三种解决方案都通过服务总线使用消息传递(命令、事件)。(就我而言)
我的主要问题是:创建包含消息的程序集并让每个解决方案引用该程序集是否是常见做法
额外积分:在
我是DDD的新手,希望澄清一些疑问。感谢您的帮助
在DDD模型中,程序集引用层次结构是自上而下的,这意味着模型可以引用基础结构,而不应该反过来。现在,如果我们在模型组件中声明所有类,那么在这种情况下,基础结构类将必须引用模型组件,以获取数据访问层(DAL)中具体存储库实现的类信息。此外,模型组件必须引用基础结构组件才能访问DAL层。我对此感到困惑!正确的方法应该是什么
我们应该在模型层或基础设施DAL层中拥有Repository和UnitOfWork接口吗?我们应该在模型层中拥有接口,但在基础设
我正在使用领域驱动设计,我对我的领域模型有一个非常清晰的了解。它包含120多个类,并且非常稳定。我们将在.NET4和C#中实现它。问题是,我们需要多语言的模型;有些属性需要以多种语言存储。例如,Person类有一个类型为string的Position属性,该属性应以英语(例如“Library”)和西班牙语(例如“Bibliotecario”)存储一个值。此属性的getter应返回英语或西班牙语版本,具体取决于某些语言参数
现在开始我的问题。我不知道如何将其参数化。我列举了两种主要的方法:
使用属
对于DDD应用程序,使用域事件是广泛认可的做法,但有一些场景对我来说很棘手
我最近正在开发一个应用程序,其中业务逻辑要求在创建新用户时,该用户也在三个独立的子系统中创建。因此,基本上,如果使用事务脚本方法,它将类似于:
public void CreateUser()
{
CreateUserInSystemA();
CreateUserInSystemB();
CreateUserInSystemC();
}
public void CreateUser()
{
我在批发系统领域工作。当某些产品交付时,会触发域NewProductsDeliveredEvent。事件包含一组包含产品代码和数量的ProductDeliveryvalue对象。如下所示:
class NewProductsDeliveredEvent {
Set<ProductDelivery> productDeliveries;
}
class ProductDelivery {
ProductCode productCode;
Quantity quantit
我有一个关于CQR中读取模型的问题
假设我们有两个有界上下文:A和B
在contextA中,我们基于contextA中的事件构建一个readmodel。我们有某种dao来访问A中的readmodel
现在假设B需要与A相同的读取模型。
据我所知,有界上下文不应该相互依赖
那么我如何使用A的模型呢?我认为有三种可能性可以解决这个问题
在A中为读取模型创建API模块,并在上下文B中使用该模块
(将是a和B之间的依赖关系)
在上下文B中创建一个与上下文A完全相同的单独读取模型
(将导致代码重复)
在B
我需要用CQR实现一个项目,但是我不确定哪些实体获得了相应的命令和查询类
如果我有类A、B和C,因为A是我的聚合根,其他的是我的聚合中的子实体,那么什么类应该有命令和查询类
我的意思是,我应该有一个QueryA、QueryB和QueryC,或者我应该只有QueryA,它将使用延迟加载带来子数据,例如
对于存储库,根据我对域模型的理解,我只考虑一个repositoria(对于我的聚合根) 查询不是按聚合进行的,而是按视图进行的。例如,假设您有一个客户帐户,并希望显示
账目清单
包含机密信息的账户详
我有一个名为TicketTissue的类,它具有以下属性:
初级的
idGroup
idModel
重量
简述
计算权重背后的逻辑相当复杂,需要查询其他实体。我是否:
把其他的实体注入这个恶心
在存储库中查询该实体中的那些实体是否比注入更好?
实现一个服务,该服务计算权重,然后在持久化之前在实体上设置权重
实施一项活动
为了补充这个问题,在创建票证时,这个实体还需要一些健壮的逻辑。。。通过电子邮件等方式通知意向方
在这个实体中实现addNew感觉不太好,我应该有服务还是工厂?这会持久化实体并发送
我试图弄清楚我是如何处理DDD和使用有界上下文的
我试着举个例子来说明我的问题。(我使用贫血课程来提高速度)
我试图找出如何在不同的有界上下文中分离域对象
我考虑了可能是雇员的域对象
假设我有两个有限的环境,人力资源部和财务部
public class Employee
{
public int Id { get; set; }
public Title Title { get; set; }
public string Forename
DDD中的域模型应该是持久性不可知的
CQRS命令我为我的阅读模型中不想拥有的一切触发事件。(顺便说一下,将我的模型分为写入模型和至少一个读取模型)
ES指示我为所有改变状态的事件触发事件,并且我的聚合根必须处理事件本身
这对我来说似乎不是很不可知论
那么,在这种持久性技术不会对域模型造成严重影响的情况下,DDD和CQRS/ES如何结合呢
读模型也在DDD域模型中吗?还是在它之外
CQRS/ES事件是否与DDD域事件相同
编辑:
我从答案中得出以下结论:
是的,对于ORM,域模型objecs的实
目前我正在学习领域驱动设计。根据我的理解,我创建了一个示例应用程序,它在国家/地区执行一些操作
我已经创建了一个名为“MyTest.Country”的类库,其中包含所有命令-
--MyTest.Country (ProjectName)
-- Commands (Folder)
--CreateCountry (: ICommand)
--DeleteCountry (: ICommand)
我有另一个名为“MyTest.CountryClient”的
我是DDD的新手,所以如果写得好,我很抱歉,但我一直在努力寻找答案
在我们的领域中,我们有一个“正常班次”的表示,例如下午:15.00-18.00。但是,可以在一周中的特定日期(周一-周日)或特定“地点”修改班次。最终结果应该是相同的班次(例如下午),但在特定的一天/特定的地点有一个新的时间
我们应该如何为这些更新的转变建模?到目前为止,我们已经做到了
一个常见的“班次”对象,可以作为正常班次应用,也可以关联到一天或一个地点
表示“换档调整”变化的模型
每个班次的独特模型,具有某种关系,因此可以
哪一层应该负责检查数据库中某个实体的存在?
假设我有一个订单作为聚合,该订单可以包含多个项目。逻辑意味着我只能向订单中添加现有项目
我是否应该在应用程序服务中这样写:
var item = ItemRepository.GetByID(id);
//throws exception if the item is null
order.AddItem(item);
或
都不是,真的
实体不会跨越聚合边界。实体是聚合的一部分,在这种情况下,聚合管理自己的生命周期;或者项目是其他聚合的一部分,在这
我听过allot关于使用DDD中的有界上下文来评估微服务的内容。你知道这到底意味着什么吗
谢谢
goaths我有一个猜测,你听到了Eric Evans在GOTO 2015上关于战略设计和微服务的谈话,所以你可能想先看一下这个捕获:
他在进一步的演讲中也谈到了这个话题:
您必须阅读DDD手册才能理解BC是什么。它类似于子域,但在代码中具体化。阅读感谢回复链接非常有帮助。。我也找到了这本书
我正在使用领域驱动设计和事件源实现一个应用程序。我正在SQL Server的DomainEvents表中存储所有域事件
我有以下汇总:
- City
+ Id
+ Enable()
+ Disable()
- Company
+ Id
+ CityId
+ Enable()
+ Disable()
- Employee
+ Id
+ CompnayId
+ Enable()
+ Disable()
每一个都封装了自己的域逻辑
在过去的几周里,我一直在开始并试图了解DDD CQR、ES和微服务。
我想我已经单独理解了他们,但不是作为一个整体,所以这就是为什么我有一些误解,我希望澄清
那么首先,微服务和DDD之间的关系是什么,你能做到一个没有另一个吗?
其次,有界上下文最终会转化为微服务吗?微服务和DDD之间没有关系。。。是的,你肯定可以做一个而不做另一个。
有界上下文是域级的,微服务是一种实现/基础设施/体系结构,如果您想
是Eric Evans在2003年提出的一套战术和战略设计原则。。。解决软件的复杂性
是一种将应
假设我有两个模型
项目和任务
一个项目可以有多个任务,但一个项目在任何时候都只能有一个状态为“进行中”的任务
据我所知,这通常作为根聚合的域不变量的一部分处理
然而,在这种情况下,与项目相关联的任务列表可能是无限的,因此我认为它不太适合,但同时项目应该控制和维护前面提到的不变量
关于如何最好地对此建模,您有什么建议吗?听起来您在项目和任务之间有一种关系,应该是1对1
project inProgress task
您的约束条件是,这种关系对于每个项目都应该是唯一的
这反过来又表明,您的项目AP
我正在做我的第一个项目与决心和有限的经验,在DDD,ES和CQR。所以,也许有一个非常简单的解决办法,我只是还没有找到
我的问题:在我的项目中,一个聚合的状态(订单的状态)实际上来自于其他聚合的状态(属于此订单的每个工作步骤的状态;可以有两个或多个工作步骤同时进行,每个步骤都有自己的状态,例如错误或完成)
经过一些研究,我的想法是在工作步骤聚合的每个命令处理程序中调用一个额外的命令(称为“updateOrderStatus”),例如:
pauseWorkStep: (state, { p
我试图用ddd来模拟两种类型的发票。
采购发票和销售发票。
简单的行为是采购发票增加库存数量,而销售发票减少。
哪一种适合ddd?
1-分别定义在两个不同聚合中实现业务逻辑的PurchaseInvoice和SalesInvoice?
2-定义一个发票聚合并使用dicriminator字段实现业务逻辑帮助?听起来像是购买和销售是两个完全不同的上下文。这意味着,发票实体可以同时存在于两者中。鉴别器是一种气味,你正在处理两种不同的事情。因此,1或2似乎都不是最佳选择。我宁愿在采购有界上下文中使用发票,
我目前正在确定系统中的实体、值对象和聚合。假设已确定以下实体:
客户,客户邮件,电子邮件,客户地址,地址,地址类型
其中客户->电子邮件是一种多对多关系,客户->地址(具有地址类型)也是如此。这些关系由CustomerAddress和CustomerMail关系对象表示
起初我认为这是直截了当的:
实体:客户、客户邮件、客户地址
值对象:电子邮件、地址、地址类型
客户是包含上述所有实体和VO的聚合的聚合根
我遇到的问题(这可能是因为我在继续学习聚合的概念)是说,您有一个供应商实体,它使用相同的地
域模型和存储库可以在单独的DLL中吗
在3层体系结构中,我想我应该将域模型放在业务层
以及数据访问层中的存储库
我感到困惑,因为我的理解是,域模型使用存储库,而存储库应该从域模型返回对象,这将导致循环依赖
我一定是误解了上面的一个或多个概念
非常感谢您的澄清,因为这已经困扰了我一段时间,谢谢。我认为您根本不应该让您的域程序集引用您自己应用程序中的任何内容。它应该是最里面的组件,它完全不知道外部的任何东西。它只是坐在那里,知道域逻辑
您的域模型不应该使用存储库,而应该使用应用程序服务。
(如果域实
可以通过服务接口从域实体调用域服务
例如-:
employee.Fire()调用IEEmployee解雇服务。我是通过接口而不是通过具体的接口调用的
这可能吗?虽然您可以在没有任何编译错误的情况下执行此操作,但我认为在域实体中调用域服务不是一个好主意
通常,如果操作影响多个实体,我们将把逻辑放在服务方法中。因此,如果fire操作只影响当前雇员,则应该封装在employee.fire()中。否则,如果影响多个员工,则应将其放入服务中,应用程序应调用service.Fire()而不是employee
在这方面有几个问题,阅读它们对我没有帮助。在Eric Evans DDD中,他使用了地址在某些情况下作为值类型的示例。对于邮购公司来说,地址是一种值类型,因为如果该地址是共享的,谁住在该地址并不重要,只要包裹到达该地址即可
这对我来说很有意义,直到我开始思考如何设计它。根据第99页的图表,他是这样写的:
+------------+
|Customer |
+------------+
|customerId |
|name |
|street |
|city
发件人:
假设公司和个人都有相同的邮件地址。
这些陈述中哪一个认为有效?
1.“如果我修改Company.Address,我希望Person.Address自动获得这些更改”
2.“如果修改公司地址,则不得影响个人地址”
如果1为true,则地址应为实体
如果2为true,则地址应为值对象
在上面的模型中,邮件地址不应该是一个值对象,因为即使公司和个人有相同的邮件,该邮件仍然没有概念标识
换句话说,如果最初是公司和个人共享初始值。address@gmail.com,但之后会收到新邮件。addre
应用程序服务通过调用和协调对工作流、基础设施服务、域服务和域实体的调用来实现客户端(即表示层)发出的命令
很少有域服务执行与应用程序服务类似的工作,这是否是一种常见做法,这意味着它们也进行和协调调用,唯一的区别是它们在更细粒度的级别上进行调用(即它们只进行和协调对其他域服务和域对象的调用)
如果是的话,有什么想法这些域服务应该是多细粒度的吗
谢谢域服务包含的域逻辑不适合任何实体,或者跨多个实体
一个经常被引用的例子是FundsTransferService。转移资金似乎不是BankAccount
在阅读了和之后,我现在陷入了一个紧迫的问题:如何应用“不要编写OSGi”的咒语
假设有界上下文是整个应用程序,而不是单个捆绑包,我应该可以自由地在API捆绑包中声明一些聚合根实体,并以DDD样式声明用于处理所述实体的存储库。现在,问题的关键是:显式存储库似乎与OSGi风格相反,因为存储库本身就是(域对象的)注册表,而这种设计避开了OSGi服务注册表。但要取消存储库,消费者需要编写OSGi以执行实体的查找
据说存储库只是一个外表——这是否意味着我应该创建一个存储库实现,它将委托给服务注册中心?这似
我面临一个设计问题,我想在两个不同的有界上下文中对同一个物理对象建模
为了尽可能精确地描述我的问题,即使我知道这只是一个实现细节,我将从我的事件源机制开始
我的事件存储机制
下面是Greg Young的CQRS文档(请注意PDF“构建事件存储”部分)的广泛启发
我有两个表,一个称为聚合,另一个称为事件(注意复数形式,因为它们是表,不是对象!),如下所示:
namespace DomainModel/WriteSide/Sales;
use DomainModel/WriteSide/Aggreg
我在我的项目中使用DDD,喜欢它的强大思想,并且独立于我的后端DB设计。
我还在前端使用MVP模式。
但最近,我遇到了将模型转换为模型>>1000个对象的性能问题,比如:
从EF存储库模型到域模型
从域模型到视图模型
同样的旅程,我应该在DB上持久化一个对象。
这是实施此模型的缺点,还是我应该遵循任何降低成本的方法 将域聚合映射到实体框架数据模型和实体框架数据模型之间,会对性能造成微不足道的影响
但为什么要一次映射1000个对象?我不了解您的需求或领域,但听起来您的设计中可能存在问题。为什么在内
当我们有特定的唯一EntityID时,EventSourcing工作得非常完美,但当我试图从eventStore而不是特定EntityID获取信息时,我遇到了困难
我将CQR与EventSourcing一起使用。作为事件源的一部分,我们将事件作为列(EntityID(uniqueKey)、EventType、EventObject(例如UserAdded))存储在SQL表中
因此,在存储EventObject时,我们只是序列化DotNet对象并将其存储在SQL中,因此,与UserAdded事件相
所以我尝试用DDD的方式重构重写我的应用程序。这是一个包含3个类的简单应用程序:
配置(名称)
环境(名称)
属性(键)
我使用它来查看和编辑每个环境的配置文件。一个配置可以被视为一个表,其中属性作为行,环境作为列
此时,配置是一个实体,环境和属性是值对象。但是现在我想要实现us ecase,为给定的环境将值设置为属性。我的第一个想法是:
class Configuration(name) {
environments = SetOf[Environment]
propertie
我的系统有一种“联系人”的语言,这是一种我们有一些信息的“幽灵用户”——它的验证规则很小,它的状态主要是联系人信息。我们还有一个“用户”的概念,即经过充分审查和注册的用户。把“用户”想象成一个充实的“联系人”
我们试图捕获的生命周期是,一旦有人使用“联系人”的信息注册,“联系人”将被“用户”取代
我们在系统中还有其他聚合根,它们引用指向“联系人”UUID的“联系人ID”。当“联系人”注册时,我们希望使用“用户”的新概念在域中表示他们,“用户”现在有自己的“UserID”UUID
我们如何保持仍然
在我的例子中,我有两个主要概念:用户(系统的主要公民)和组。
组有两个子集合:等级和角色。没有团队,等级和角色就没有意义。
当用户被分配到组时,我们还必须选择1个角色和1个等级,并将它们分配给用户和组之间的关系
问题:
我这里有多少聚合根?从用户方面看,它显然是一个用户(系统的主要概念),但它与组的关系如何?DDD规则禁止AFAIK引用聚合根以外的实体
DDD规则禁止AFAIK引用聚合根以外的实体
嗯,我不会说这是“DDD规则所禁止的”。。。有时你别无选择。我必须考虑与根的集合相关联的“实体集
我是DDD和CQRS的新手,我正计划构建一个简单的应用程序来提高我的技能。
我计划做的是一个简单的出租车公司应用程序
要求:
客户点了一辆出租车
客户一次只能有一个订单
司机点菜
驱动程序一次只能有一个订单
驱动程序转到客户端
客户进入驾驶室
课程开始了
课程结束
客户购买,司机付款
等等
我可以看到可以有三个聚合:客户机、订单和驱动程序。我想把它们分成不同的微服务。你认为这是个好主意还是我应该从一个微服务开始
我现在专注于叫出租车。首先,我需要检查客户是否还没有指定课程,然后我可以创建订单。创
我们正在创建一个系统,负责贷款发放。
我们从一开始就采用领域驱动的设计方法。
我们正处于识别子域和上下文映射的阶段
有趣的是,我们的一个业务用例本身就是通过360度监控全天候维护系统的正常运行时间
将应用程序监视添加为子域的一部分有意义吗?当然有意义。一旦领域专家请求一个功能并为其付费,它应该作为核心/支持/通用领域出现在上下文映射中
通常,如果某个功能由业务用户(不是开发人员或DevOps)使用,那么它应该位于上下文映射中。未来该领域很可能会有更多功能,如报告、订阅计划等
在阅读了大量文章后,我意识到如果一个概念/上下文存在聚合根,那么我们需要为整个概念/上下文建立一个存储库
如果是这样,我看到内部实体将不会有任何存储库。如果是,这些内部实体是如何保存到数据库的
我在聚合根下有许多内部实体。因此,如果我想知道是否需要将所有内部实体保存在聚合根存储库下,它将变得臃肿。请建议在这种情况下可以做什么
此外,我的内部实体将在持久性级别访问它们自己的每个表。如果不允许我以这种方式存储内部实体,请更正
示例
我想我有一个餐厅作为一个聚合根。它可以对名为Review的实体进行分
我有产品存储库。我想使用redis作为缓存。我创建了缓存repo
当我想要得到产品的时候。首先,我去缓存repo,如果不存在,我查询主数据库。如果里面有产品。我写入缓存并返回
选项1)我通过DI在产品存储库中获取缓存存储库并在其中使用
选项2)我在command handler with product repository中的应用层中获得缓存存储库,并分别使用这两种存储库。在我看来,您是受技术需求(即Redis的使用)而不是业务需求(即为什么需要缓存?性能问题、延迟?)驱动的
但是,要总结SO
是否有任何示例应用程序显示使用Enterprise Library 5.0实现DDD。如果您感兴趣,请查看此项目
恐怕DDD与EntLib无关。。。你到底想知道什么?DDD是一种设计理念。它与任何特定的库或框架无关。最接近的说法是,框架的设计考虑了DDD(如Sharp架构),我指的是用于数据访问的企业库。但我真正想要的是DDD模式(实体、VO、聚合等)的完整示例。Entlib的数据块实际上只是ADO.NET的一个浅包装,以减少使用时的麻烦。它不会影响您实际构建数据访问的方式。如果你真的喜欢DDD
我需要一些关于在分布式DDD应用程序中实现价值对象列表的具体指导。以下是我所拥有的:
我的应用程序基于运行在服务器上的RESTful服务应用程序,该服务器向多个客户端应用程序提供服务。我的一个实体Customer具有一个Region属性,该属性包含对许多Region值类型之一的引用。区域列表存储在后端数据库中,但我们不提供维护此列表的接口。任何更改都将直接在数据库中进行(因为这种更改非常罕见),并且很可能是名称更改,而不是添加/删除。有时,就像扩展到新市场一样,可以添加一个新项目,因此对列表的要
假设我有一个具有实体的域,该实体的一个属性是真/假属性,类似于活动/非活动
正确的建模方法是什么
使用布尔值False=Inactive和True=Active
使用枚举:
公共枚举状态
{
活动=1,
非活动=2
}
我认为使用Enum是正确的方法,但是使用布尔属性也没有错
你们DDD的人是怎么想的?如果它是真/假对,那么布尔值就是好的。没有必要把事情过分复杂化
如果将该值用作方法参数,枚举甚至类的可读性可能会更好。但是,同样,您可以考虑调用两种不同的方法。
枚举可能存在的问题是,可能会使用无
我一直在DDD做一个小项目。我到处都看到值对象是不可变的,因此,不能修改它。只有实体
我将使用每个人都使用的例子。地址。假设地址是客户实体的VO(也是根聚合)。如果用户更新其地址,这在任何购物车场景中都有效,那么我应该怎么做?我必须修改该VO地址,以便将其持久化到数据库中。也就是说,这个VO必须有一个标识,以便我在数据库中识别它。除非NHibernate使用映射来处理它,对吧。林克托斯不是这样的。
或者我想我必须创建一个新的聚合,其中地址是一个实体?然后几乎在我需要地址的地方都有一份地址副本
不
我对以下几点有点困惑。我应该使用导航属性到达我想要到达的地方,还是应该询问存储库?例如:我有下面的课程
public class Vehicle
{
public IList<Equipment> Equipment { get; set; }
}
public class Equipment
{
//.. Properties..
}
公共级车辆
{
公共IList设备{get;set;}
}
公共级设备
{
//…财产。。
}
就DDD而言,建议采用什么方式获取与专
如果问题的标题不是很清楚,请原谅,因为我真的不知道如何很好地解释这个问题。我试试看
我正在为一个域建模,其中我有一个叫做点的AR。我可以在那个点上做一些动作来修改它的状态。这些是在AR类中或通过某些域服务实现的。到目前为止,我觉得一切都很好
当我在一个点上有长时间运行的进程时,问题就来了。我想对一个进程的单个执行做一些具体的工作,比如监视它的状态、暂停、取消、重试等等,并且要有一些视图来聚合这些进程的执行。对我来说,这似乎是另一个背景(BC)的一部分。这真的是一个单独的背景吗?只是某种行为应该成
一段时间以来,我一直在处理领域驱动的设计。不幸的是,我在总量方面有一些问题
比如说,我喜欢模拟一所大学的结构。这所大学有一些系(系),每个系都有一些班级。有一条规则,每个部门都必须是唯一的,所以每个班级都必须是唯一的。例如,类的名称需要是唯一的。如果我理解正确,那么“大学”似乎是我的聚合根,“系”和“类”是这个聚合中的实体
还有另一个聚合根“Professor”,因为它们可以在全球范围内访问。他们将被分配到一个班级。我不确定它是否被允许,因为聚合根应该只指向另一个聚合根,而不是它的内容
如何处理
是否允许DDD工厂直接为域对象设置属性?
例如:
创建域实体的正常方法是使用构造函数。因此,您可以通过一个或多个构造函数接受所需的参数
如果使用域工厂,则不会改变这一点。当实体创建更为复杂时(例如,从多个对象创建实体,或者在创建过程中涉及某些逻辑),可以使用域工厂,但您仍然可以使用实体的构造函数来创建实体。创建域实体的正常方法是使用构造函数。因此,您可以通过一个或多个构造函数接受所需的参数
如果使用域工厂,则不会改变这一点。当实体创建更为复杂时(例如,从多个对象创建实体,或者在创建过程中涉及某些
当我们一直在谈论贫血模型是反模式的时候,我在想它是否足够好用于微服务
正如许多人所提到的,Martin Fowler称之为贫乏的modelor事务脚本实际上适用于小型应用程序。虽然采用单片结构是可以理解的,但我们必须使用更复杂的结构来处理复杂性
然而,使用微服务,我们不太可能在一个服务中包含太多的逻辑。相反,服务通常只包含单个域中的相关逻辑,这通常很容易理解和处理。在这种情况下,在microservice中使用事务脚本模型完全合适吗?Martin Fowler的企业应用程序架构模式可能是一个合理
我很好奇如何将来自多个聚合根的数据连接到一个事件源聚合根的读取模型中。可以尝试举一个简单的例子:
如果我有一个名为Cart的聚合根,它在其事件流中支持以下事件(括号中的属性-请记住这是一个简单的示例):
当使用来自此事件流的数据投影读取模型时,这是正常的。例如,我可以投影一个cart对象,其外观如下:
Cart(cartId: Int, products: List[Product])
Product(productId: Int, userLicenses: List[UserLicense
我有下面的值对象代码,它通过一些昂贵的数据库操作验证CustCode
公共类CustCode:ValueObject
{
私有客户代码(字符串代码){Value=code;}
公共静态结果创建(字符串代码)
{
if(string.IsNullOrWhiteSpace(代码))
返回结果。失败(“代码不应为空”);
//验证该值对数据库是否仍然有效。代价高昂且速度缓慢
如果(!ValidateDB(code))//或web api调用
返回结果。失败(“数据库验证失败”);
返回Result.S
1 2 3 4 5 6 ...
下一页 最后一页 共 30 页