事件采购 - 汇总建模

时间:2016-04-22 01:14:11

标签: event-sourcing event-store

两个问题 1)如何建模它们之间的聚合和引用 2)如何组织/存储事件以便有效地检索它们

以这个典型用例为例,我们有Order和LineItem(它们是聚合,Order是聚合根)和Product聚合。 由于LineItem需要知道哪个产品,所以有两个选项1)LineItem直接引用Product aggregate(这似乎不是最佳实践,因为它违反了aggregate作为一致边界的想法,因为我们可以直接从Order更新Product aggregate ())然后LineItem只有ProductId。

看起来第二种选择是要走的路......你觉得这里怎么样?

但是,出现了另一个问题,即构建订单读取/查看模型。在此Order视图模型中,它需要知道哪些产品是有序的(即ProductId,Type等)。典型的用例是报告,而CommandHandler也可以使用此Product对象来执行逻辑,例如是否有太多特定产品等。为了做到这一点,鉴于这些数据是在两个单独的聚合中的事实,那么我们需要1+数据库往返。由于我们使用事件来构建模型,因此伪代码如下所示 1)对于给定的订单ID(guid,订单聚合ID),我们为它加载所有事件; - 第一次数据库访问 2)然后构建一个Order聚合,然后我们知道Order中引用了哪个ProductId; 3)对于ProductIds列表,我们为它加载所有事件; - 第二次数据库访问

如果我们构建一个非常大的对象图(很多不同的聚合),那么最终可能会有一些数据库访问(每个都很慢)......你的想法在这里是什么?

由于

1 个答案:

答案 0 :(得分:0)

  

以这个典型用例为例,我们有Order和LineItem(它们是聚合,Order是聚合根)和Product聚合。

订单汇总对您所描述的方式有意义。 "产品聚合"更可疑;您是否询问模型是否允许更改产品,或者您是否告诉模型产品已更改?

如果产品可以在未事先咨询订单的情况下进行更改,则LineItem必须包含该产品。对产品(也称为ProductId)的引用是可以的。

  

如果我们构建一个非常大的对象图(很多不同的聚合),那么最终可能会有一些数据库访问(每个都很慢)......你的想法在这里是什么?

对于阅读,报告等 - 您不会在历史中添加新事件 - 一个可能的答案是提前做慢工作。异步进程侦听事件存储中的写入,然后将这些事件发布到总线。订阅者在观察到新事件时构建新版本的报告,并缓存结果。 (搜索关键字:

当客户端要求提供报告时,您可以从缓存中提供一个报告。所有的工作都完成了,所以它很快。

对于命令处理程序,答案更复杂。业务规则应该在域模型中,因此让命令处理程序尝试验证命令(而不是域模型)有点破碎。

命令处理程序可以加载产品以查看状态可能是什么样的,并使用命令数据将该信息传递给聚合,但是不清楚这是一个好主意 - 如果客户端将发送一个要运行的命令,你需要使用Product数据充实Order命令,为什么不直接将命令产品数据添加到命令中,并跳过中间人。

  

CommandHandler也可以使用此Product对象来执行逻辑,例如是否有太多特定产品等。

这个例子有点模糊,但猜测一下:如果可用库存不足以履行订单,您正在考虑阻止下订单的情况。

对于真实世界的库存 - 仓库中的实体书 - 这可能是错误的方法。首先,模型本身是错误的;如果您想知道仓库中有多少产品,您应该查询仓库,而不是产品。其次,物理仓库不受您的模型约束 - 在仓库聚合上调用addProduct方法并不会导致产品神奇地出现在那里。

第三,它可能与您的领域专家无论如何都不匹配。如果模型说仓库没有足够的产品,你认为利益相关者是否想要系统

  1. 告诉购物者在其他地方购买产品,或者......
  2. 接受订单,并与供应商联系以获得新的交货。
  3. 提示:如有疑问,请仔细阅读amazon.com如何做到这一点。