域驱动设计 – DDD – 强制使用具有小聚合根的不变量

前端之家收集整理的这篇文章主要介绍了域驱动设计 – DDD – 强制使用具有小聚合根的不变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我第一次尝试使用DDD,我遇到了聚合设计的问题.

我的申请包含3个实体;图,节点,链接.这些实体中的每一个都有一个name属性,可以由用户修改(我认为’name’不适合作为Entity id).图表包含节点集合,节点具有传出链接集合(出于此问题的目的,忽略传入链接是安全的).每个节点一次只能与一个图形关联(但可以在图形之间移动),同样,每个链接只能在任何给定时间与一个节点关联(但可以移动).

我试图强制执行的不变量是所有实体名称在其父集合中是唯一的.使用上面描述的体系结构,不变量在实际集合上,因此我决定集合所有者(图形和节点)都应该是聚合根.

我遇到的问题是如何在Node上强制执行名称不变量?在链接上它很容易,因为它隐藏在节点AR内部,因此节点可以确认所有链接重命名/移动都不会破坏这个不变量.但据我所知,没有什么可以阻止Node的直接重命名,这可能会破坏不变量.最终的一致性在这里不是一个可接受的选项,这必须是一个真正的系统不变量.

我正在考虑的方法是让Node.Rename()实际强制执行不变量,但我担心的是这涉及查看其父图形以检查重命名是否有效.这并不“感觉”正确 – 感觉Graph应该是强制执行此命名空间约束的那个,并且Node根本不应该知道它.

我希望这是有道理的,我期待听到人们的想法.

编辑:上面提供的域模型是整个域的简化子集.对于在单个AR中持有的所有实体来说太复杂了……

正如您在评论中已经总结的那样,唯一的聚合根应该是Graph.

聚合和聚合根之间存在差异.在您的示例中,Graph和Node都是聚合,但负责管理整个聚合的对象是Graph.所以这就是根.

了解对象是否为聚合根的最简单方法是问自己:

Does it make sense to have just this object,detached from its parent?

如果答案为否,那么它可能不是聚合根.例如,当单个节点不是父图形的一部分时,它可能没什么用处.这就是为什么你通常只有聚合根的存储库;防止自己访问不属于其相应聚合根目录的对象.

现在转向不变量.你说过(强调我的):

all [Node] names are unique within their parent [Graph]

你基本上在那里回答了你的问题.在单个节点的上下文中,说它的名称是唯一的没有意义.但是在图的上下文中它确实如此,因为它是Graph的不变量,而不是Node.因此Graph负责protecting this invariant.

至于“神聚合根”,从全球业务角度来看,拥有一个聚合根并不罕见.但DDD的一个重要方面是识别系统中的不同上下文.您的系统可能具有包含许多Graph对象的高级根.在管理图形的高级环境中,您可能甚至对图中的低级链接对象不感兴趣.

根据上下文对域对象进行建模非常重要.这是我在过去几个月里意识到的最重要的事情之一.大多数人都知道DDD是因为存储库,或者是因为实体和值对象,但这些并不像有界上下文那么重要.

尽管Something只有一个商业概念,但拥有代表Something概念的多个模型,每个上下文的单个实现完全没问题.一个实现可能是聚合根,而另一个实现只是更大聚合的一部分,所有这些都取决于上下文.

常见的软件咒语是关于代码重用,DRY等等,所以起初认为有多个类代表相同的业务概念是错误的.但是,一旦我能够放下这种感觉,并意识到每个实现都有自己的责任,它使事情变得如此简单:)

猜你在找的设计模式相关文章