【发布时间】:2013-01-24 03:13:01
【问题描述】:
简介
这个问题是关于 DDD 和事件溯源,其中聚合中的实体(聚合根除外)具有事件生成行为。
示例
下面是我描述的情况的一个示例,我确定我想在聚合内的其他实体中封装一些逻辑。这可能涉及暂停对实际示例以及它是否是一个好模型的怀疑。 :)
我正在尝试为 DeliveryRun Aggregate Root (AR) 建模,这是车辆执行交付的行程。在它离开之前,它必须有一个最新的DeliveryManifest。它的“最新性”向我表明DeliveryManifest 是AR 定义的DeliveryRun 一致性边界内的一个实体。
到目前为止还好。
我为此使用了事件溯源方法 - Greg Young 教授并在 Regalo library 中实施的方法。这意味着如果 AR (DeliveryRun) 没有任何行为,则它们实际上不需要任何实体(例如,SalesOrder 可能没有 SalesOrderLines,因为它记录了诸如 ItemsAdded/ItemsRemoved 之类的事件) .
但是,DeliveryManifest 周围有一些逻辑。具体来说,一旦首次请求清单,当项目被添加到交付时,需要创建清单的新版本。这意味着我们可以确保司机不会在没有可用的最新清单的情况下离开。
如果我要将逻辑封装在 DeliveryManifest 对象内(不会被序列化和存储;我们使用的是事件源,它不是 AR),我如何捕获事件?
我正在考虑的选项
事件是否应该由
DeliveryManifest实体生成,但保存在DeliveryRun本身(然后需要知道如何在从事件存储加载时将这些事件重播到DeliveryManifest中) ?是否应该没有
DeliveryManifest(可能作为数据结构除外)并且所有逻辑/事件都由DeliveryRun直接实现?DeliveryManifest是否应该是它自己的 AR 并确保DeliveryRun被告知当前清单的 ID?由于这将清单对象置于DeliveryRun的一致性边界之外,我需要构建一些事件处理来订阅与清单相关的DeliveryRun中的更改,以便可以相应地更新/无效等。实现与 Udi 的 DomainEvents 模式类似的不同样式来捕获事件。这意味着更改 Regalo 库,尽管我认为它可以很容易地支持这两种模式。这将允许捕获聚合中所有实体生成的所有事件,以便针对 AR 保存它们。我需要考虑一个加载/重播的解决方案......
【问题讨论】:
-
想解释一下软件如何防止送货卡车司机带着过期的清单离开?您可能希望减轻它曾经发生的风险,但不阻止它。此外,您可能想要一本记录实际发生的事情(即使清单是错误的,在特定的运行中,您想知道哪个清单被带走了)与计划发生的事情。
-
经过反思,在我看来,manifest 和 run 的生命周期是不同的,但恰好在某个时间点重叠。在实际交付开始之前,清单可能会多次更改。计划交付运行时,您可能会指示应携带哪个清单。也许人们应该在计划交付后停止对清单进行更改(也许没有,或者在实际交付发生之前的某个时间点,人们可以更改清单)。显然,我缺乏领域知识......
-
好的,所以我希望在涉及 DDD 的问题上得到这样的 cmets,但实际上我的问题是基于我已经正确建模的假设,因此我该如何实现封装AR 以外的实体中的逻辑?如果我是在我的 AR 上的行为方法中编写 C# 代码,它是否可以委托给其他封装逻辑的实体类?如果是这样,如何捕获这些实体生成的事件?如果它们自己不生成任何事件,那么这些事件是从哪里来的?
标签: oop domain-driven-design event-sourcing