2017-03-06 57 views
1

聚合根的成员实体指向根实体(不是相反方向)可以吗?指向根实体的DDD /聚集根/成员实体

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

我正在评估人口与人口会员之间的关联方向。在另一端还有另一个实体,人(自己的AR,人口会员有人参照)。

在ER(数据库)世界中,我们通常会从人口会员朝向人口(人口成员是人口与人之间的多对多关系中的关联表)进行关联。

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

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

有什么想法?

+1

也许这是以某种方式与我的问题相关:http://stackoverflow.com/questions/9804815/associations-traversal-direction 有了这个亮点:“当实体A和实体B之间存在关联时,经常会发现自己只使用AB而不会使用BA这可能是因为A是一个聚合根,并且始终是您的起点,因为无论您在何处操作B等,您都已经有了对它的引用。 它表明(至少)当实体与根实体直接关联时,方向总是来自根实体。对? –

+0

[Associations'遍历方向]的可能的重复(http://stackoverflow.com/questions/9804815/associations-traversal-direction) – guillaume31

回答

1

好吧,让我们这个问题分成两个部分:

  1. 是否确定为成员单位召开参考它的总根源?
  2. 一般性综合建模规则

让我们从1开始:

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

好了,现在到了第二点:

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

哦,另一件重要的事情 - 通常只是通过id来引用其他聚合根目录是个好主意。这样,您就没有复杂对象图的问题,并且您不必担心在单个事务中修改其他聚合(聚合根不应该修改其他根)。如果您需要在聚合之间进行通信 - 请改用事件。

请参阅由沃恩弗农伟大的系列文章:

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

我认为这些文章可以帮助您了解集结建模的概念。

+0

我想补充说,为了从数据库模型中拆分领域模型(如您所命名的它)你可以使用CQRS,其中有两个分离的模型:写模型(又名Aggregates)和读模型(UI/Presentation可以看到什么)。如果您选择CQRS,那么这种分离非常自然且清晰。 –

+0

@ConstantinGALBENU感谢您的评论。是的,为写和读创建单独的模型是一个好主意。这些模型甚至可以使用不同的数据库,根据不同层次的具体需求进行调整。但是,在我的答案中,我使用“数据库模型”术语来描述直接从数据库映射的纯数据(无逻辑)类。根据我们使用的技术,我们的域类可以与我们的数据库映射类几乎相同或者完全不同(例如,域类使用复杂对象与数据库映射类中的平面原语)。 –