【问题标题】:Why limit commands and events to one aggregate? CQRS + ES + DDD为什么将命令和事件限制在一个聚合中? CQRS + ES + DDD
【发布时间】:2015-12-25 15:42:28
【问题描述】:

请解释为什么在进行 CQRS、ES 和 DDD 时同时修改多个聚合是一个坏主意。有什么情况还是可以的吗?

以 PurgeAllCompletedTodos 等命令为例。我希望此命令通过将 IsActive 设置为 false 来引发一个事件,该事件更新每个已完成的 Todo 聚合的状态。

为什么这样不好?

我能想到的一个原因:

在更新域状态时,最好将事务限制在整个状态中明确定义的部分,以便在更新期间只有这部分需要写锁定。这样做将允许在不同的聚合上并行进行许多写入,这可以在一些极其繁重的情况下提高性能。

【问题讨论】:

  • "事件可以更新任何域状态吗?"和“为什么将命令和事件限制为 1 个聚合?”对我来说,这似乎是两个独立的、不相关的问题。
  • 是的,你是对的。我会修改问题。
  • 我已将问题的另一部分移至此处:stackoverflow.com/questions/32823747/…

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


【解决方案1】:

问题的答案在于“聚合”的含义。

首先我要说的是,您不是在修改“n”个聚合,而是在修改“n”个实体。

一个聚合包含多个实体,它只是一个事务的概念,当你需要修改多个实体的状态时使用聚合(模式) /strong> 在您的应用程序中进行事务处理(全部修改或没有)。

现在,为什么要使用一个命令修改多个聚合?

如果你觉得有这个需要,在做任何其他事情之前检查你的聚合边界,看看你是否可以修改它以删除对 1 命令 -> 'n' 聚合的需要。

一个聚合可以包含许多相同类型的实体,因此对于您的命令 PurgeAllCompletedTodos,您还可以考虑将事务边界从单个 Todo 扩展到包含所有用户待办事项的聚合 UserTodosAggregate,并让它管理单个用户待办事项的所有命令。
通过这种方式,您可以在单个事务中修改用户的所有待办事项。

如果这仍然不能解决您的问题,因为假设需要清除应用程序中每个用户的所有已完成的待办事项,您仍然需要向“n”个聚合发送命令,聚合边界没有“ t 帮助,因此我们可以考虑使用 AllApplicationTodosAggregate 来管理命令。
可能这不是最好的解决方案,因为正如您所说,该命令会阻止应用程序的所有待办事项,但是,请始终检查它是否是一个很好的权衡(这部分阻塞在 Blue DDD 的书和红皮书)。

如果我需要修改一些实体并且不能将它们放在一个聚合中怎么办?

如前所述,修改多个聚合的命令由于事务而不好。如果修改3个聚合,第一个是好的,然后关闭服务器呢?

在这种情况下,您所做的是需要管理大量单个修改以防止系统不一致。 它可以使用流程管理器来完成,其职责是修改所有聚合,向它们发送正确的命令并在发生故障时进行管理。

聚合仍然接收它自己的命令,但进程管理器负责以它知道的方式发送它们(一次一个,并行,每次 5 个,你想要什么)
因此,您可以制定一个策略来管理两个事务之间的故障,并做出如下决定:“如果某事失败,则回滚到目前为止所做的所有修改”(向每个聚合发送回滚命令),或“如果操作失败重复每 30 分钟 3 次,如果不起作用则回滚”,“如果出现故障,则为系统管理员创建通知”。

(抱歉,帖子太长了,至少希望对您有所帮助)

【讨论】:

  • 很好的解释。很好解释。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-12
  • 2020-03-20
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
相关资源
最近更新 更多