我还是DDD新手。在域模型中,我有一个Component
的聚合,它可以由子组件组成,也可以本身是另一个父Component
的子组件。换句话说,我有一个组件层次结构。
需要两个操作:AddSubComponent()
和AddToParent()
。在执行这两个操作时,如何强制执行层次结构中不存在循环的不变量?是否应通过域事件强制执行?或者只引用聚合中的父级和子级,然后在聚合本身中递归检查嵌套组件,如果操作会创建循环?
注意:我使用C#,并使用EF Core持久化域模型。
编辑我通过将每个组件视为一个集合来解决问题。每个人都有自己的父母和子女。
AddSubComponent(Component c)
检查c
是否已经是子组件,并在与组件的父组件和c
的子组件进行检查后返回或仅添加c
作为子组件。然后触发一个由应用层处理的域事件,以验证整个图是否包含循环,并调用c.AddToParent()
AddToParent(Component c)
执行与上面的操作相同的逻辑,但只添加到父级,还触发一个域事件,该事件在应用程序层处理,也只调用parent.AddSubComponent()
。
通过这种方式调用任何方法都将确保仅用于聚合的原子一致性,并且整个层次结构的最终一致性由应用层确保。此外,上面的所有操作都封装在一个事务中。因此最终只保留有效的层次结构。
在这种情况下,我宁愿实现单向关系。当使用事件时,就像您提到的那样,这将是微不足道的,因为您可以在执行AddSubComponent
之后发出事件,所以AddToParent
将异步发生,作为一种反应。然而,在一个只保持状态的系统中生成事件并不是一件小事,因为您必须使用发件箱或CDC来避免不可靠的两阶段提交。
如果您只维护父级的子级列表,则没有必要这样做。当然,它可能不适合您的上下文,因为像确保组件只有一个父级这样的情况在模型本身中是不可能的,并且需要域服务,该服务会查询组件的父级以查看有多少。
您可以在方法本身中强制执行它。
添加子组件
在"添加子组件"方法中,检查要添加的组件是否已作为子组件或子组件的子组件存在。
添加到父项
将";AddSubComponent";将如上所述进行检查。