简介
此问题与 DDD 和事件溯源有关,其中聚合内除聚合根之外的实体具有事件生成行为。
示例
下面是我所描述的情况的示例,我确信我想将一些逻辑封装在聚合内的其他实体中。这可能涉及暂停对实际示例以及它是否是一个好模型的怀疑。 :)
我正在尝试对DeliveryRun
聚合根(AR)进行建模,它是车辆执行交付的行程。在出发之前,它必须拥有最新的 DeliveryManifest
。它的“最新性”对我来说意味着 DeliveryManifest
是 AR 定义的 DeliveryRun
一致性边界内的实体。
到目前为止还好。
我为此使用事件溯源方法 - Greg Young 教授的方法并在 Regalo library 中实现。这意味着如果 AR (DeliveryRun
) 没有任何行为,则实际上不需要有任何实体(例如 SalesOrder
可能没有 SalesOrderLines
,因为它记录了诸如 ItemsAdded
/ItemsRemoved
之类的事件)。
但是,DeliveryManifest
周围需要一些逻辑。具体来说,一旦首次请求 list ,当将项目添加到交付中时,需要创建新版本的 list 。这意味着我们可以确保司机在没有最新可用 list 的情况下不会出发。
如果我将逻辑封装在 DeliveryManifest
对象中(该对象不会被序列化和存储;我们使用的是事件源,而不是 AR),我该如何捕获事件?
我正在考虑的选项
事件是否应该由
DeliveryManifest
实体生成,但针对DeliveryRun
本身保存(然后需要知道如何将这些事件重播到DeliveryManifest
从事件存储加载时)?是否应该没有
DeliveryManifest
(可能作为数据结构除外)并且所有逻辑/事件都由DeliveryRun
直接实现?DeliveryManifest
是否应该是它自己的 AR,并确保DeliveryRun
获知当前 list 的 ID?由于这会将 list 对象置于DeliveryRun
的一致性边界之外,因此我需要构建一些事件处理来订阅DeliveryRun
中与 list 相关的更改,以便它可以相应地更新/失效等。实现与 Udi 的 DomainEvents 模式类似的不同样式来捕获事件。这意味着更改 Regalo 库,尽管我认为它可以相当容易地支持这两种模式。这将允许捕获聚合内所有实体生成的所有事件,以便将它们保存到 AR 中。我需要考虑一个加载/重放的解决方案......
最佳答案
我会避免将 DeliveryManifest
设为另一个聚合根,除非它是一致性边界。
许多示例没有处理这个问题。似乎聚合根应该负责从其内部的实体收集事件,并将它们分发到正确的实体以供稍后加载,这似乎是您的选项 1。
如果没有与 DeliveryManifest
关联的行为,选项 2 也非常好。
关于oop - DDD、对象图和事件溯源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14771132/