这是一个菜鸟(我认为)事件采购 问题
作为一个例子,我们有:
鞋匠鲍勃:
假设我们有一个" shoe_repair_order" (聚合根?)
我们发生了爱丽丝的修鞋订单 有时候七月,之前鞋匠鲍勃搬家 他的营业地点在街区。
让我们说爱丽丝正在查看12月份的订单。 显然,她不必知道鲍勃的业务。 当她看到她的订单时,我认为她应该看到(至少)旧的 营业地点和/或 "订购于5 Baker Street(新地址为11 Baker street - 10月6日更新)"。
问题:我们如何设计Event-Sourced系统以显示订单的旧地址?
OR
我们是否发出" OrderLocationAdded"活动,并提及地址 " 88d8 AT VERSION 1 ",以便我们知道查找我们营业地点的第1版。 我们将不得不重播" shoemaker_business_locations" 直到我们看到"版本X"我们的地址(在我们的案例中为版本1)。 这就是我们必须对所有版本为的旧订单所做的事情 地址低于当前设置的版本(版本1)。
其他一些方式?
也许我们的读模型只是存储不同版本的所有地址信息,当我们查询某个版本时 我们不必在我们的写模型中重放事件,而只是从我们的读模型中获取版本1的地址?
答案 0 :(得分:1)
我认为实现这一目标的最佳方式最终取决于您设计域模型的方式,但这就是我如何解决问题:
我们需要在域模型中表示地址。这意味着,地址将是值对象,实体或聚合。在这三者中,一个地址实际上只能是一个价值对象或该域中的一个实体,因为我们是修鞋应用而不是地址簿。实体具有某些属性,例如通过其ID来区分,以及某些限制,例如仅作为一个聚合的一部分,地址似乎不会满足。因此,我会在这个域中看到一个Address是一个Value Object。
在" shoe_repair_order"上定义OrderLocationAdded事件时聚合,您需要决定是否在事件中包含地址的完整详细信息,或使用对地址的引用。由于Address是一个Value Object(它由数据而不是ID定义),答案是在事件中包含Value Object。这样,当您重放事件以构建订单的当前状态时,它仍将具有原始地址的详细信息。
如果您还要在订单上显示新地址,您可以使用其他事件(例如BusinessMovedToNewLocation)和新地址的详细信息,并将其添加到订单中。此事件不会替换原始地址,它只会允许您显示业务现在位于其他位置的信息性消息。
答案 1 :(得分:1)
您的问题的答案当然取决于您如何定义您的域模型(特别是如何定义您的聚合)。我将解决此问题的方法是有两个聚合:
ShoeMaker Aggregate(在您的情况下,存储所有信息,如鞋匠业务的名称,有关此业务的信息'所有者,此鞋匠的所有地址列表,其中每个地址可以包含电子邮件等信息,电话号码,以及一个名为current的bool字段,当前地址可以为true。我想这个AR会有一个名为 - " ChangeShoeMakerCurrentAddress"这会引发一个名为" ShoeMakerAddressesChanged"
订单汇总(包含客户名称,价格,详细信息,订单日期,交货日期等订单的所有信息。)
我们假设我们有一个名为" ShoeMakerOrderReadModel"它可以订阅由ShoeMaker Aggregate和Order Aggregate引发的事件。此读取模型侦听事件并将它们非规范化为POJO / POCO对象。这个POCO / POJO模型可以有一个鞋匠地址列表(其中每个地址都可以包含电子邮件,电话号码和一个名为current的bool字段等信息,对于当前地址可以是真实的。)此AR绝对可以订阅&#34 ; ShoeMakerAddressesChanged"来自ShoeMaker Aggregate的事件,然后更新鞋匠地址列表。
我希望这有帮助!
答案 2 :(得分:0)
由于CQRS,答案很简单:你不能在BusinessMovedToANewLocationEvent
中听取 OrderDetailsReadModel
。当Business address
发生时,您只需在Order details
Read model
中的当前 OrderPlacedEvent
查找和存储。
通过这种方式,您不必在活动中加入任何Address value object
。 Read model
完成所有工作。
如果您因其他原因需要,您可以收听此活动,但只是不要更新地址。例如,Read model
可能更智能,另外还有一个addressChangedInTheMeanTime
boolean
标记,以告诉Alice
她看到的Address
是旧的,但因此取决于您的业务需求。
答案 3 :(得分:0)
以下是一些选项: