【问题标题】:Is there an accepted way of dealing with events containing ID of another aggregate?是否有一种可接受的方式来处理包含另一个聚合 ID 的事件?
【发布时间】:2016-09-08 14:39:58
【问题描述】:

假设为客户生成了发票。这个特定的事件看起来像这样:

invoice.raised {
   "id": "4dbcff82-6f35-4155-9aec-f8185c1f932f",
   "total": "50.00",
   "description": "Order 01133",
   "customer_id": "c2206843-414d-454f-9894-57c6b11b9c00"
}

这是一个相当简单的示例,它指的是发票所属的客户集合。

当我想创建发票视图并且想在发票中嵌入客户的名字时,困难就显现出来了。我可以做两件事 - 丰富原始事件以包含客户的姓名或加载客户视图以在我构建发票视图时找出名称是什么。 现在这不是一个非常复杂的示例,但在某些情况下,丰富事件变得几乎无法管理,因为我最终将各种聚合的大量属性复制到特定于其他聚合的事件中。

除了丰富事件之外,是否有一种普遍接受的方法来处理这个问题?因为现在每次引发 invoice.cancelled 事件,我都必须再次包含发票金额,以便我可以使用新余额更新客户视图。

【问题讨论】:

    标签: domain-driven-design event-sourcing eventstoredb


    【解决方案1】:

    在某些情况下,几乎无法再丰富事件,因为我最终会将各种聚合的大量属性复制到特定于其他聚合的事件中。

    没错,它使您的活动更难管理。

    所以我想说,在您构建阅读模型时,只需 customer_id 并询问客户姓名就足够了

    • 它可以在投影时构建非规范化视图。
    • 可以在查询时,基于发票和客户构建结果视图模型(对于此用例,您可以拥有专用的客户列表,仅包含 customer_idcustomer_name

    因为现在每次引发 invoice.cancelled 事件,我还必须再次包含发票的 amount,以便我可以使用新余额更新客户视图。

    invoice.cancelled 事件是由 Invoice 聚合根触发的,我希望它拥有amount,所以很自然地将amount 放入invoice.cancelled 事件中。

    invoice.raised 事件也由 Invoice 聚合根触发,但它不拥有客户名称。无论如何,它无法检查客户名称在特定时间点是否一致。这就是为什么在构建读取模型时可以简单地查询它而不是嵌入客户名称的原因。

    顺便说一句,有一本关于设计事件的好读物 - 6 Code Smells with your CQRS Events – and How to Avoid Them

    【讨论】:

      【解决方案2】:

      当我想创建发票视图并且想在发票中嵌入客户的名字时,困难就显现出来了。

      除了丰富事件之外,是否有一种普遍接受的处理方式?

      如果你能提供帮助,你不想走丰富事件的道路——这会增加实现中的耦合,从而使更改模型的成本更高。

      UI 组合技术可能会引导您朝着有用的方向发展。乌迪·达汉(Udi Dahan)多次写过关于他们的文章。一些例子

      基本情节 - InvoiceView 不是获取客户状态并使用该状态生成客户视图,而是 InvoiceView 将一部分责任委托给客户组件本身

      InvoiceView (e : invoice.raised) {
          InvoiceWidget(e.id)
          CustomerWidget(e.customer_id)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-27
        • 2015-09-19
        • 1970-01-01
        • 2012-03-15
        • 1970-01-01
        • 2018-08-22
        相关资源
        最近更新 更多