调和父母/子女关系中的小聚合和不变式

时间:2018-08-29 18:40:19

标签: domain-driven-design

首先,我对聚合的理解/假设。 *聚合是唯一可以直接访问的域对象。如果聚合中有子级,则必须通过聚合来访问它们。 *聚合可以通过其ID引用其他聚合。这意味着我可以通过其存储库加载聚合A,通过该存储库获得对聚合B和加载B的ID引用。 *如果同时单独更新根聚合和子实体,则大型聚合可能会导致并发问题。

例如,我有一个基于章节的会员制。各章都有成员。用户应该能够同时对不同的成员进行更改,从而使我能够将Chapter和Member各自设置为自己的集合。

但是我们有一条规则说

  • A)成员必须属于某个章
  • B)一个章节不能有两个具有相同名称和出生的成员 日期。

我觉得我应该有这样的代码

 var member = chapter.EnrollMember(memberInfo);

如果该章已具有与为B传递的参数匹配的成员,则该代码应该引发错误。但是,如果该章聚合中仅具有对其他成员的ID引用,那么应该如何获取这些成员?

  • 通过成员存储库吗?
  • 将“成员名称”移出“章”聚合并移至域服务中?

注意:这是一种假设情况。我正在寻找这种情况如何建模,而不是是否应该以这种方式建模。

1 个答案:

答案 0 :(得分:1)

在大范围内对大型集合进行集合验证通常是不实际的。如果使用关系数据库,则可以使用唯一约束来保护该不变式。

另一种方法可能是依靠最终的一致性,在这种情况下,您可以在规则破损后检测出规则破损并发出补偿措施(自动或手动)。为了确定是否可以选择最终一致性,您必须评估为企业打破这一规则的成本,这就是为什么对假设情景进行建模没有那么大的帮助。在现实世界中,您会问为什么为什么会员不能拥有相同的姓名和出生日期(在现实世界中完全可能)如此重要?如果违反该规则,企业将为此付出多少费用?如果在发送命令之前先在UI上对其进行了验证(例如,UI上的唯一性检查)等,那么发生的可能性有多大。

如果从某种意义上说,成员唯一性策略非常重要,必须非常一致,但是过于复杂而无法建模为唯一约束,那么您可以对仅维护最小状态以保护不变性的AR进行建模,而所有其他成员细节在单独的AR上处理。例如,成员的namebirthdatestatus可以在ChapterMember内的Chapter实体上建模,而ChapterMemberProfile AR可以保留其他不需要设置验证的详细信息。

//Enroll
var memberProfile = chapter.enrollMember(name, birthdate, avatarFilePath);

transaction {
    save(memberProfile);
    save(chapter);
}

//Change avatar for a given chapter
var memberProfile = find(chapterId, name, birthdate);
memberProfile.changeAvatar(avatarFilePath);

save(memberProfile);

//Disenroll (you could also modify memberProfile in the same transaction for this specific use case -- if needed)
chapter.disenrollMember(name, birthdate);

save(chapter);