我尝试了解从一个Aggregare Root到另一个Aggregare Root填充属性的最佳方法。
我有Model Aggregate Root
,Category Aggregate Root
,Filter Aggregate Root
每个Model
都可以有一些Filter
列表,并且可以位于Category
之一。 Category
可以Filter
继承Model
。更新Category
的{{1}}属性后,必须将Model
从Filter
继承到Category
,并在Model
属性更新时Filter
,Category
的所有Models
都必须继承新值。所有继承的Category
都无法更新,但可以手动添加过滤器。
我发明的一种方式"使用Filters
的状态包含Process manager
和Category filter
。
所以我会有这样的行为:
Models list
UpdateCategoryFilter(command) - > CategoryFilterUpdated(事件)Category AR
AddCategory(命令) - > CategoryAdded(事件),RemoveCategory(命令) - > CategoryRemoved(event),InheritFilter(command) - > FilterInherited(event),RemoveInheritedFilter(command) - > InheritedFilterRemoved(event)Model AR
CreateFilter(命令) - > FilterCreated(事件)Filter AR
FilterInheritance
correlationIdResolver
,[categoryId
,CategoryFilterUpdated
]事件触发CategoryUpdated
这是正确的方法吗?还有其他方法吗?
答案 0 :(得分:3)
请记住,聚合用于在进行状态更改时保护域不变量,而不是用于简单的CRUD。目前尚不清楚您的域是什么,以及可以将哪种命令发送到“模型”,其中保护不变量需要知道模型的“过滤器”是什么。
如果需要针对聚合的状态验证命令,或者命令将影响可能发送到聚合的未来命令的处理,则只需要向聚合发送命令。目前尚不清楚这是否适合您。模型聚合是否必须根据它具有的过滤器验证命令/发出事件?如果没有,处理这个的方法是纯粹在读取端执行 - 读取端可以跟踪模型的当前过滤器,并且客户端/进程可以根据需要使用它。因此,您的模型读取投影只需要侦听CategoryAdded,CategoryFilterUpdated等,以更新模型的读取视图。
如果您确实需要过滤器来验证模型命令或发出适当的事件来响应这些命令,那么您所获得的似乎是一个选项。但检查业务需求以查看是否可以在模型聚合之外进行过滤等是有价值的,因为在聚合之间复制命令会增加耦合 - 在发送InheritFilter等命令和客户端发送之间也存在竞争条件需要该过滤器的模型命令,这似乎是一个问题,可能需要客户端处理来轮询模型以备命令。
答案 1 :(得分:2)
看起来非常像你在做CRUD风格的数据操作操作而不是采用域方法。
您可能遇到的另一个问题是假设您可以使用Aggregate在UI上显示信息。聚合原则上不具有任何外部可见属性(除了ID之外没有getter)。如果他们这样做,他们将无法很好地封装。最好使用读取模型在UI上使用。本文可能会让您更好地了解典型的CQRS应用程序的结构:CQRS + Event Sourcing – A Step by Step Overview
假设您正在寻找使用DDD风格的方法,我首先要看看您的聚合。我不知道您的域名,但从表面视图来看,它看起来只有1个聚合根。不知道它会被称为什么,因为我对你的域名一无所知。
我不希望,例如,真正的用户会说“InheritFilter”之类的东西。您可能还希望看一下本文,以帮助您了解如何为事件命名,并暗示您的命令:6 Code Smells with your CQRS Events – and How to Avoid Them
我希望这有助于澄清您的一些问题。我个人发现DDD,CQRS和事件采购非常困难。我不得不忘掉一堆东西。但是因为它我是一个更好的开发者。
希望这有帮助。