域驱动设计中的根聚合问题

时间:2010-12-10 12:00:27

标签: domain-driven-design

我有两个Entities Publisher和SocialAccount,两者都是独立的,并且具有多对多的关系。两者都是根聚合,现在我无法通过Publisher获得社交帐户,我想将M到M的关系转换为1到M.所以我介绍了另一个实体注册,将有{PubID,SocID,CreateDate}。现在,发布者和注册之间存在1到M的关系,注册和SocialAccount之间存在1到1的关系。所以出版商将

  

列表<注册> _Registrations {get; set;}

但是当我创建聚合边界时,Publisher是我的根,并且根据聚合原则,只有根聚合将保持对另一个根聚合的引用。但这里注册持有参考。

所以我违反了集合原则,因为注册是连接社交账户实体。

2 个答案:

答案 0 :(得分:4)

您对聚合概念的使用似乎不正确。聚合中的对象实际上可以保存对其他聚合的引用。规则是外部对象不能保持对聚合内某事物的引用。

在Registration对象上,您似乎已创建它以避免某些聚合聚合关系。这不是创建对象的原因。如果您的域中实际存在注册,请创建并对其进行建模。如果它不在您的域中,请不要仅将其添加到遍历某个路径。

添加了注册后,您说它无法保留对社交帐户的引用,因为它是Publisher的一部分。这不是规则,但更重要的是注册突然成为发布者聚合的一部分?仅凭出版商拥有注册集合?

聚合是一组对象,它们被视为一个用于维护状态和不变量的单元。关系的存在本身并不会赋予聚合成员资格。

但现在看看另一边。使用社交帐户注册为1比1。如果我们删除社交帐户,是否仍然有一个注册与发布者?如果没有,则注册可能实际上是SocialAccount聚合的一部分。这就是我们创建聚合的原因 - 确保对象及其关系在状态更改后始终有效。如果删除SocialAccount的状态更改包括删除与该帐户关联的所有注册,我们希望将其包含在聚合中以强制执行该规则。

现在你确实违反了“聚合规则” - 你有一个从Publisher到对象的外部关系,注册,这是SocialAccount聚合的内部部分。

这些概念不仅仅是规则,它们有原因。您需要查看聚合的真正含义,了解规则实际说明的内容以及它们的真正含义,以及它们首先存在的原因。然后相应地重新评估您的关系和汇总定义。

答案 1 :(得分:0)

首先,我们需要一个抽象来封装模型中的引用。

AGGREGATE是一组关联对象,我们将其视为一个单元,用于数据更改。

每个AGGREGATE都有一个根和一个边界。边界定义了AGGREGATE中的内容。根是AGGREGATE中包含的单个特定ENTITY。根是AGGREGATE中唯一允许外部对象保持引用的成员,尽管边界内的对象可以保持对彼此的引用。除根之外的实体具有本地标识,但该标识只能在AGGREGATE中区分,因为没有外部对象可以从根ENTITY的上下文中看到它。

你怎么看待Ssyphus?