指向根实体的DDD /聚合根/成员实体

时间:2017-03-06 15:57:53

标签: associations domain-driven-design aggregateroot

聚合根的成员实体是否可以指向根实体(而不是相反)?

假设我有人口AR(其中人口是根实体,而人口成员是其中一个成员实体)。

我正在评估人口与人口成员之间的关联方向。另一端有另一个实体,Person(自己的AR,人口成员对Person的引用)。

在ER(数据库)世界中,我们通常会建立一个从人口成员到人口的关联(人口与成员是人口与人之间多对多关系的连接表)。

但我认为在DDD世界中,我应该打破这种习惯,并将关联从人口(概念模型)转向人口成员。

无论如何,在此之前,我想确认是否(在某些其他情况下可能)我们被允许从成员实体到根实体的关联。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

好的,我们将这个问题分成两部分:

  1. 成员实体是否可以保留对其聚合根的引用?
  2. 常规聚合建模规则
  3. 让我们从1开始:

    不,通常子实体不应该引用聚合根。聚合根是整个聚合的入口点,必须保持其一致性边界。这意味着,必须通过根实体(通过调用根实体的方法在oop中)转发对聚合的每个更改。聚合根可以返回对子实体的引用,但它们必须是瞬态的。此外,客户端不应对聚合根之外的子实体执行更改 - 否则可能会违反一致性。考虑到这一点,我并没有真正看到子实体持有对其根的引用的原因(从客户的角度来看 - 您已经可以访问根,不是吗?)。我现在看到的唯一例外是,您需要将模型转换为某些特定需求(例如,表示层需要根实体ID才能生成有意义的JSON输出)。但是,即使在这种情况下,您可能会创建一个单独的读取模型或提供专门的汇编程序来构建所需的DTO。

    好的,现在到第二点:

    您似乎正在尝试以与构建数据库模型相同的方式对域实体进行建模。在DDD中,我们应该首先关注模型的业务需求和行为。在构建有意义的域模型时,数据关系并不那么重要(我们稍后会对其进行细化)。因此,首先您应该专注于从领域专家那里收集业务案例场景。聚合应该建立在真正的业务不变量上。您应该与您的团队(包括业务成员)一起创建一个通用模型。在几次知识运算会后,您的设计很可能看起来完全不同。也许Person不是真正的聚合根,而只是一个价值对象?也许你甚至不需要人口成员实体?聚合的最常见设计只是具有多个值对象的单个(根)实体。除此之外 - 我经常创建完全独立的数据库模型,几乎没有连接(除了id)到域模型。我使用转换层(映射器组件)在域< - > dbmodel之间进行转换。在我最近的项目中,我的db模型与域层非常不同(它专门针对持久层的需求进行了调整 - 因此,例如使用了许多平面属性 - 不是完整对象而是简单的原始值)。在关系数据库的情况下,您甚至可以明确地提供双向关系(事实上,您甚至不需要使用任何orm)。将db模型与域模型分离有很多优点。设计肯定更柔顺。但是,db< - >之间的映射成本(开发人员工作)。域层对于简单项目来说可能太大了。在这种情况下,我通常从普通模型开始,然后重构为可分离的层。

    哦,另一个重要的事情 - 通常只能通过id引用其他聚合根。这样,您就不会遇到复杂对象图的问题,也不必担心在单个事务中修改其他聚合(聚合根不应修改其他根)。如果您需要在聚合之间进行通信 - 请改为使用事件。

    请参阅Vaughn Vernon的伟大系列文章:

    http://dddcommunity.org/library/vernon_2011/

    我认为这些文章可以帮助您理解聚合建模概念。