【问题标题】:More than one Aggregate per Event Stream in Event Sourcing事件溯源中每个事件流的多个聚合
【发布时间】:2022-02-15 23:29:37
【问题描述】:

假设一个事件流是一个事务边界并且聚合是一个写入模型来强制执行不变量,我可以有两个或多个聚合专用于一个事件流吗?如果由于性能或过于复杂的设计原因无法选择一个大型聚合体?

例如,我有以下由一个事件流表示的域模型:

{
  "Products": [{
      "Id": 1,
      "Name": "Call-Centre",
      "Services": [
          {
              "Id": 10,
              "Name": "CloudStorage",
              "Price": 250,
              "Discount": 100
          }
      ]
}]

我需要强制执行两个不变量。第一:每个产品的服务必须是唯一的(按名称)。第二:服务折扣值不能超过实际价格。 现在我考虑使用两个聚合: ProductAggregate 包含用于强制执行第一个不变量的服务集合; ServiceAggregate 仅包含用于执行第二个的服务信息。 我的解决方案是否存在一些缺陷?

【问题讨论】:

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


    【解决方案1】:

    一般来说,您不能将聚合嵌套在其他聚合中。他们可以通过根引用另一个聚合。您可以通过另一个聚合对给定聚合进行所有访问。

    例如,产品聚合可能是这样的:

    {
      "Id": 1,
      "Name": "Call-Centre",
      "Services": {
        "CloudStorage": 10
      }
    }
    

    服务聚合可能是:

    {
      "Id": 10,
      "Name": "CloudStorage",
      "Price": 250,
      "Discount": 100
    }
    

    如果服务实际上是产品的子级(产品 1 的 CloudStorage 与产品 2 的 CloudStorage 不同),那么您可以通过在服务中使用 Product 字段对其进行编码(并且很可能有一个域约束,一旦服务与产品相关联,服务中的Product 字段就不能更改)。涉及关系的操作可能会变成 sagas(例如,将服务添加到产品或更新服务名称)。将这种关系编码到服务 ID 中可能也是值得的,尽管如果 ID 可以是字符串或其他内容,这可能会更容易。

    因为它们是不同的聚合,所以它们在概念上是不同的事件流(因为聚合至少与事件流一样定义事务边界)。将 2 个事件流投影为一个可能很有用:该投影可能能够正确地对两个源流之间的事件进行排序。这种排序的逻辑将取决于域(例如,知道哪些操作可以交错,哪些可以假设不可以(例如,因为它们是由 saga 协调的))。

    【讨论】:

    • 非常感谢,我认为我的域模型做得过火了。我有一些非常复杂的概念要建模,所以我被困了几天。但是你清除了我的想法!
    猜你喜欢
    • 2018-12-28
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2018-10-03
    • 1970-01-01
    • 2020-05-27
    • 2019-07-16
    相关资源
    最近更新 更多