是否有一种可接受的方式来处理包含另一个聚合 ID 的事件?
Is there an accepted way of dealing with events containing ID of another aggregate?
假设为客户生成了发票。这个特定事件看起来像这样:
invoice.raised {
"id": "4dbcff82-6f35-4155-9aec-f8185c1f932f",
"total": "50.00",
"description": "Order 01133",
"customer_id": "c2206843-414d-454f-9894-57c6b11b9c00"
}
这是一个相当简单的示例,它指的是发票所属的客户集合。
当我想创建发票视图并且想在发票中嵌入客户姓名时,困难就显现出来了。我可以做两件事 - 丰富原始事件以包含客户的姓名或加载客户视图以在我构建发票视图时找出名称是什么。
现在这不是一个非常复杂的示例,但在某些情况下,丰富事件几乎变得难以管理,因为我最终将各种聚合的许多属性复制到事件中,这些属性对其他聚合非常特定。
除了丰富事件之外,是否有普遍接受的处理方式?因为现在每次引发 invoice.cancelled 事件时,我都必须再次包含发票金额,以便我可以使用新余额更新客户视图。
Difficulty manifests itself when I want to create Invoices view and I want to embed Customer's name in an invoice.
Is there a universally accepted way of dealing with this apart from enriching events?
如果可能的话,您不想走上丰富事件的道路——这会增加实施中的耦合度,从而使更改模型的成本更高。
UI 组合技巧可能会指导您朝着有用的方向发展。 Udi Dahan 多次写过关于他们的文章。一些例子
基本图 - 不是 InvoiceView 获取客户状态,并使用该状态生成客户视图,而是 InvoiceView 将一部分责任委托给客户组件本身
InvoiceView (e : invoice.raised) {
InvoiceWidget(e.id)
CustomerWidget(e.customer_id)
}
in some cases it becomes almost unmanageable to enrich events anymore as I end up with a lot of properties of various aggregates copied into the event that is very specific to some other aggregate.
没错,这会使您的活动更难管理。
所以 我会说只要 customer_id
就足够了,并在构建读取模型时询问客户名称:
- 可以在投影时,在构建非规范化视图时。
- 它可以在查询时,当基于发票和客户构建结果视图模型时(对于此用例,您可以有专门的客户列表,仅包含
customer_id
和 customer_name
)
Because everytime now the invoice.cancelled
event is raised I will have to also include the amount
of the invoice once again, so that I can update Customers view with new balance for instance.
invoice.cancelled
事件由 Invoice 聚合根触发,我预计,它拥有 amount
,因此很自然地将 amount
放入 invoice.cancelled
事件中。
invoice.raised
事件也由发票聚合根触发,但它不拥有客户名称。它无法检查特定时间点的客户名称是否一致。这就是为什么您可以在构建读取模型时直接查询而不是嵌入客户名称的原因。
顺便说一句,有一本关于设计事件的好书 - 6 Code Smells with your CQRS Events – and How to Avoid Them
假设为客户生成了发票。这个特定事件看起来像这样:
invoice.raised {
"id": "4dbcff82-6f35-4155-9aec-f8185c1f932f",
"total": "50.00",
"description": "Order 01133",
"customer_id": "c2206843-414d-454f-9894-57c6b11b9c00"
}
这是一个相当简单的示例,它指的是发票所属的客户集合。
当我想创建发票视图并且想在发票中嵌入客户姓名时,困难就显现出来了。我可以做两件事 - 丰富原始事件以包含客户的姓名或加载客户视图以在我构建发票视图时找出名称是什么。 现在这不是一个非常复杂的示例,但在某些情况下,丰富事件几乎变得难以管理,因为我最终将各种聚合的许多属性复制到事件中,这些属性对其他聚合非常特定。
除了丰富事件之外,是否有普遍接受的处理方式?因为现在每次引发 invoice.cancelled 事件时,我都必须再次包含发票金额,以便我可以使用新余额更新客户视图。
Difficulty manifests itself when I want to create Invoices view and I want to embed Customer's name in an invoice.
Is there a universally accepted way of dealing with this apart from enriching events?
如果可能的话,您不想走上丰富事件的道路——这会增加实施中的耦合度,从而使更改模型的成本更高。
UI 组合技巧可能会指导您朝着有用的方向发展。 Udi Dahan 多次写过关于他们的文章。一些例子
基本图 - 不是 InvoiceView 获取客户状态,并使用该状态生成客户视图,而是 InvoiceView 将一部分责任委托给客户组件本身
InvoiceView (e : invoice.raised) {
InvoiceWidget(e.id)
CustomerWidget(e.customer_id)
}
in some cases it becomes almost unmanageable to enrich events anymore as I end up with a lot of properties of various aggregates copied into the event that is very specific to some other aggregate.
没错,这会使您的活动更难管理。
所以 我会说只要 customer_id
就足够了,并在构建读取模型时询问客户名称:
- 可以在投影时,在构建非规范化视图时。
- 它可以在查询时,当基于发票和客户构建结果视图模型时(对于此用例,您可以有专门的客户列表,仅包含
customer_id
和customer_name
)
Because everytime now the
invoice.cancelled
event is raised I will have to also include theamount
of the invoice once again, so that I can update Customers view with new balance for instance.
invoice.cancelled
事件由 Invoice 聚合根触发,我预计,它拥有 amount
,因此很自然地将 amount
放入 invoice.cancelled
事件中。
invoice.raised
事件也由发票聚合根触发,但它不拥有客户名称。它无法检查特定时间点的客户名称是否一致。这就是为什么您可以在构建读取模型时直接查询而不是嵌入客户名称的原因。
顺便说一句,有一本关于设计事件的好书 - 6 Code Smells with your CQRS Events – and How to Avoid Them