Domain driven design 层次系统中的聚合根与聚合

Domain driven design 层次系统中的聚合根与聚合,domain-driven-design,aggregateroot,Domain Driven Design,Aggregateroot,我已经做了很多关于DDD的研究,在聚合与聚合根的概念上有点结巴 假设我正在尝试建立一个严格的层次结构中存在的空间游戏模型,其中包含一个包裹其中所有内容的扇区实体。它可以有一个天文馆系统的集合,每一个都可以有一个恒星的集合,恒星可以有一个行星的集合,行星本身可以有一个月亮的集合 我希望所有这些对象要么与该扇区关联,很好地位于层次结构中,但也可以不与任何扇区关联。每个项都可以与它上面层次结构中的对象具有0或1关系。。。如果需要,可在乙醚中漂浮。我希望能够删除一个行星而不删除它拥有的所有月球实体,但这

我已经做了很多关于DDD的研究,在聚合与聚合根的概念上有点结巴

假设我正在尝试建立一个严格的层次结构中存在的空间游戏模型,其中包含一个包裹其中所有内容的扇区实体。它可以有一个天文馆系统的集合,每一个都可以有一个恒星的集合,恒星可以有一个行星的集合,行星本身可以有一个月亮的集合

我希望所有这些对象要么与该扇区关联,很好地位于层次结构中,但也可以不与任何扇区关联。每个项都可以与它上面层次结构中的对象具有0或1关系。。。如果需要,可在乙醚中漂浮。我希望能够删除一个行星而不删除它拥有的所有月球实体,但这是可以选择的


我是否错误地认为,在这个场景中,它们都应该是自己的聚合根,并引用它们所包含的聚合根实例?或者扇区应该是实际的聚合根,将所有内容作为层次结构顶部的对象进行编排?

记住,某些内容可以是一个用例中的聚合,也可以是另一个用例中的聚合根。如果您的用例是AddPlanetarySystemToSector,则Sector是您的聚合根。如果您的用例是AddMoonToPlanet,那么Planet就是AR

区别在于,除非AR及其拥有的所有聚合满足所有业务规则,否则不应保存AR。AR级别越高,您必须测试和满足的业务规则就越多。因此,您的用例应该尽可能具体,并以适当的AR为目标


如果这会带来问题,一个解决办法是让ARs拥有自己的值对象,而不是聚合。因此,一个部门将拥有天文馆系统。如果扇区需要修改PlanetarySystem,它可以启动PlanetarySystem用例来执行正确的操作。

聚合根不应包含对另一个聚合根的引用。您应该使用id来引用关联的聚合,或者使用包含该id和一些其他相关数据的值对象

任何漂浮在乙醚中的东西都是聚合根,因为它有自己的生命周期

我认为,就域而言,层次结构应该以单向方式工作。如果需要基于更高级别的包含查询较低级别的项,则需要联接或需要将相关的更高级别标识符/数据反规范化到较低级别的项中


我的建议是尝试将任何聚合保持在单个级别,但如果这不可行,那么尝试更深的聚合,但很快就会变得笨拙。

那么聚合根是动态的,基于用例?我哪儿都没读过。如果实体依赖于用例,为什么我看到的许多示例都让实体实现了IAggregateRoot接口?因此,对我来说,将上面描述的对象定义为聚合根可能是更好的策略,但任何引用都应该是作为ID,理想情况下,只作为表示这些ID的ID值对象。那么,我会在域服务或其他东西中协调这些对象之间的关系吗?您应该尝试在聚合根中放置尽可能多的行为。如果某个方法不适合特定的聚合根,那么您可能正在使用多个聚合根实例来影响该行为,而域服务将是合适的。如果协调这些关系符合域服务定义,那么一定要使用它们。然而,对于域服务的使用应该是明智的,因为过度使用可能会使您的域有些贫乏。