3

考虑具有许多属性的聚合。例如用户组。如果我想发布一个 UserGroupCreatedEvent 我可以做两件事:

  1. 将刚刚创建的 UserGroup 中的属性复制到 UserGroupCreatedEvent 并复制它们的值。或者:

  2. 在 UserGroupCreatedEvent 中引用新的 UserGroup

在许多示例中,例如 Axon 的联系人应用程序,我看到了属性重复。我想知道为什么,如果在现实世界的 CQRS 应用程序中,这不是很多开销,开发人员选择引用聚合来代替。

4

2 回答 2

4

事件是 DTO,它意味着跨越边界。直接包含聚合存在以下问题:

  • 聚合是一个仅在其自身有界上下文中才有意义的概念;
  • 一个事件应该只包含相关的变化,而不是概念的全部状态;
  • 因为一个事件是一个 DTO,在某一时刻它会被(反)序列化,这将是一个正确封装对象的技术问题;
  • 每个接收处理事件的组件/上下文都将依赖于定义聚合的组件;

这些是领域事件应该只是相关状态变化的扁平表示的主要原因。

PS:如果您需要在事件中包含整个状态,则可能是事件设计不当,或者您正在处理简单的数据结构。通常聚合包含一些值对象和/或封装一些业务约束。

于 2015-08-28T14:58:55.027 回答
3

领域事件的一个重要属性是它们是不可变的。考虑到这一点,您提到的两种可能性有很大不同:

  • 复制属性会记录它们在UserGroup创建时的值。
  • 引用UserGroupby ID 只是告诉您 aUserGroup已创建,但不是它当时拥有的属性。如果UserGroup在此期间已删除,则意味着信息丢失。

您复制的属性仅取决于该差异。您是否需要能够 UserGroup在创建时查找例如 a 的名称?将其添加为属性。如果不是(并且如果预计不会需要它),请不要。

此外,域事件具有全局范围(即它们在您的 BC 之外是有意义的),因此您应该包括您的 BC 之外的客户需要理解域事件的所有信息。

请注意,将整个聚合根对象附加到域事件违反了域事件的不变性规则,因此这很可能是一个坏主意。

于 2015-08-28T14:57:23.933 回答