聚合根与分层系统中的聚合

Aggregate roots vs aggregates in a hierarchical system

我一直在对 DDD 进行大量研究,并且在聚合与聚合根的概念上有些磕磕绊绊。

假设我正在尝试对存在于严格层次结构中的 space 游戏进行建模,其中包含一个 Sector 实体,该实体环绕其中包含的所有内容。它可以有一个 PlanetarySystem 的集合,每个可以有一个 Star 的集合,星星可以有一个 Planet 的集合,它们自己可以有一个 Moon 的集合

我希望所有这些对象都与 Sector 相关联,在层次结构中位置很好,但它也可以不与任何扇区相关联。每个项目都可以与它上面的层次结构中的对象有 0 或 1 的关系......如果需要的话漂浮在以太中。我希望能够删除 Planet 而不删除它拥有的所有 Moon 实体,但可以选择完成。

在这种情况下,我是否认为这些都应该是它们自己的聚合根,并引用它们包含的聚合根实例?或者 Sector 应该是实际的聚合根,将所有内容编排为层次结构顶部的对象?

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

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

如果这会带来问题,解决方法是让 AR 拥有自己的值对象而不是聚合。因此,一个部门将拥有 PlanetarySystemVO。如果该部门需要修改 PlanetarySystem,它可以启动执行适当操作的 PlanetarySystem 用例。

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

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

我认为就域而言,层次结构应该以单向方式工作。如果您需要基于更高级别的包含查询较低级别的项目,那么您要么需要连接,要么需要将相关的更高级别 identifiers/data 反规范化为较低级别的项目。

我的建议是尝试将任何聚合保持在一个单一的层次深度,但如果这不切实际,那么尝试更深入的东西,但它很快就会变得笨拙。