Domain driven design DDD:选择聚合根
在我的例子中,我有两个主要概念:用户(系统的主要公民)和组。 组有两个子集合:等级和角色。没有团队,等级和角色就没有意义。 当用户被分配到组时,我们还必须选择1个角色和1个等级,并将它们分配给用户和组之间的关系 问题: 我这里有多少聚合根?从用户方面看,它显然是一个用户(系统的主要概念),但它与组的关系如何?DDD规则禁止AFAIK引用聚合根以外的实体 DDD规则禁止AFAIK引用聚合根以外的实体 嗯,我不会说这是“DDD规则所禁止的”。。。有时你别无选择。我必须考虑与根的集合相关联的“实体集合”的大小。有时,您可以在同一聚合中维护关联,并使用某种“延迟负载”来避免资源消耗。弗农的iDDD书[1]围绕这个具体案例提供了一些建议和用例。看看他的博文[2] [1]Domain driven design DDD:选择聚合根,domain-driven-design,aggregate,Domain Driven Design,Aggregate,在我的例子中,我有两个主要概念:用户(系统的主要公民)和组。 组有两个子集合:等级和角色。没有团队,等级和角色就没有意义。 当用户被分配到组时,我们还必须选择1个角色和1个等级,并将它们分配给用户和组之间的关系 问题: 我这里有多少聚合根?从用户方面看,它显然是一个用户(系统的主要概念),但它与组的关系如何?DDD规则禁止AFAIK引用聚合根以外的实体 DDD规则禁止AFAIK引用聚合根以外的实体 嗯,我不会说这是“DDD规则所禁止的”。。。有时你别无选择。我必须考虑与根的集合相关联的“实体集
[2] 根据您在一致性方面的业务需求,您至少有以下选项:
另外,如果您需要保留对另一AR中嵌套实体的引用,那么您应该重新考虑聚合根边界,因为您的设计很可能是错误的。我将更改一些单词,看看它是否有帮助(假设): 我有
订单
和产品
。当我将产品
添加到订单
时,我必须选择存储
和颜色
您将如何对此进行建模
color
很可能是一个值对象,但Store
不是。我会选择一个OrderItem
Value对象,它包含一个color
Value对象和一个StoreId
值来捕获关系。Order
将包含一个OrderItem
条目列表
删除color
条目很好,因为我们已经将该位反规范化到OrderItem
中。我们可以使用另一个值对象来表示存储
,但通常我们不会删除存储,也不会进行处理来处理删除,或者更典型的是,使用引用完整性约束来防止删除已使用的存储
如果您考虑删除<代码>订单< /代码>,则只删除<代码> OrthuttIs>代码>关联。
在您的例子中,
User
和Group
可能是聚合根,我将添加一个UserGroup
(或者康斯坦丁使用的UserAssignment
)。UserGroup
包含关联和相关位。但是,您必须确定真正的域结构。或者您可以使用最终一致性。基本上,没有父组,角色和级别都没有意义。它就像:“你好,我是国王[角色]。”什么[群体]的国王。“NullPointerException的”。应用程序本身非常以用户为中心,一切都围绕着用户的概念发展。在第二个选项中,碰巧我们有两个聚合-用户和组,对吗?但是用户分配(用户实体中的嵌套实体)引用组聚合中的嵌套实体。这是你的意思还是我不明白你的意思?然后使用选项1和2的组合。我还试图让您了解在设计聚合时如何思考:一致性边界。没有绝对的答案。我们可以根据您的需要进行讨论,以便理解,但没有人可以确切地告诉您当前的解决方案:实现5个聚合根:用户、组、排名、角色和用户分配。角色和等级与其父组有关系,因为用户通常希望按照特定顺序遵循该关系(foobar[group]的国王[Role]),而且该应用程序的阅读量很大。接下来,我们只创建一个GroupService并将所有不变量推送到那里(例如:组中只能有一个king-createRoleForGroup(组,角色)->loadKingRoleForGroup(组ID)->found nothing->save(角色))。这种方法还允许我为角色制定自定义规范(如get all kings),从而优化查询。我将写操作(它们遍历组,从而保护不变量)和读操作(只需要信息)分开。如果我想删除一个组-我首先检查活动的用户分配,如果它们存在-暂停执行(用户是事件源,我们必须先取消分配用户)。如果不是-删除其子聚合及其本身。这种方法有效吗?