我们想为一个仓库应用程序建模。让我们假设我们确定了以下现实世界对象:
有以下限制:
首先,我们有一个操作:
当然,这是非常简化的。
这应该如何建模?
我认为 Stockitem 可能是一个值对象。一种解决方案是将整个仓库建模为具有调色板和隔间实体的聚合体。在这种情况下,移动操作可以在其约束(不变量)方面没有任何问题地实现。但是这种方法有明显的缺点。此聚合的事件日志将无限增长。由于聚合版本控制等原因,两个移动操作无法并行执行。从 ddd 的角度来看,这对我来说感觉不合适。
另一种方法是使每个调色板和每个隔间成为自己的聚合体。但是移动操作将如何实现呢?
问题 1:谁加载引用的聚合?
我认为它应该坚持调色板。调色板可以引用它所在的隔间(它是一个聚合)。但是这个引用是如何实现的(CQRS/ES)?移动命令的命令处理程序显然将从调色板存储库加载调色板聚合并在其上调用移动方法。谁装载引用的隔间?谁装载了它应该移到的隔间?我读到聚合不应访问存储库。命令处理程序应该加载两个隔间吗?是否应该将隔间作为参数提供给 move 方法?或者命令处理程序应该将当前隔间设置为调色板并将目标隔间作为参数?
问题 2 和 3:聚合之间的约束和双向关联
约束条件呢?要检查目标隔间是否为空,隔间需要知道存储在其中的调色板。这将是应该避免的双向关联。并且因为它们是不同的聚合,所以它们不能在同一个事务中更新。是否有调色板触发域事件以通知隔间它将移动到它?它是否必须作为具有撤消操作的传奇来实现?如果两个 Action 发生冲突,一个赢了,但是失去的调色板无法移回,因为旧的隔间在此期间被填满了怎么办?
对于这个非常简单的问题,这一切对我来说似乎非常复杂。
在书籍和示例中,这一切似乎都非常清楚。但是如果我尝试使用它,我似乎做错了。
有人可以指导我正确的方向吗?
最佳答案
问题 1
我认为除了这里的业务分析之外,您还需要进行一些事务分析。
如果您的域是高度协作的(这就是 DDD 推荐的用途),移动到给定隔间的频率如何?在跨越 2 Compartment
的事务下发生 Move 操作在争用方面是否可行?聚合(源和目标) ?或者最终的一致性是否就足够了,其中源隔间将通过调色板离开它的事件向世界发出信号,而目标隔间稍后会以异步方式以某种方式被告知调色板正在加入它?
在短时间内“处于不确定状态”的调色板是完全可以接受的,这是您需要咨询领域专家的问题。
问题2
双向关联并不是唯一的解决方案。你可以问 PaletteRepository
对于所有具有 CompartmentID X 的 Palettes。或者,Compartment 可以(应该)有一个 Palette ID 列表,而不是对它们的完整引用。
总的来说,我认为你应该首先看看你问自己的所有设计问题是否有商业意义/答案。领域专家通常会对最终一致性是否现实或需要立即一致性,在发生冲突时应该发生什么等方面有受过教育的意见。
关于domain-driven-design - 如何使用 DDD/CQRS/ES 为仓库应用程序建模?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30477918/