首页 > 解决方案 > 单个命令是否应该处理多个聚合?

问题描述

在 CQRS 和 DDD 中,聚合是事务边界。因此,我一直以这样一种方式对命令进行建模,即每个命令总是只针对单个聚合。当然,从技术上讲,可以编写一个处理多个聚合的命令处理程序,但这不会在单个事务中,因此不会是一致的。

如果您实际上必须处理多个聚合,我通常会使用流程管理器,但这有时会让人感觉开销很大。此外,据我了解,流程管理器始终只对域事件做出反应,而不是直接由命令处理。因此,您需要决定将起点放在哪个聚合上。

我已经看到有些人使用所谓的域或应用程序服务来解决这个问题,它们也可以接收命令,然后在多个聚合上工作——但在这种情况下,流程的事务性质会丢失。

举一个简单的例子,更好地说明场景:

在哪里放置触发初始加入过程的命令,以及调用它的什么?user.join(group)感觉是对还是错group.welcome(user)。我可能会选择第一个,因为它更接近于无处不在的语言,但无论如何……</p>

如果我有一些高于聚合的东西,比如前面提到的服务,那么我可以运行一些东西,比如:

userManagement.addUserToGroup(user, group);

然而,这个addUserToGroup函数随后需要调用这两个命令,这反过来意味着它必须处理正在处理的两个命令——这与拥有单独的聚合和将聚合作为事务边界有些违反直觉。

对此进行建模的正确方法是什么?

标签: domain-driven-designcqrs

解决方案


可能值得在最终一致性和集合验证上查看 Greg Young 。

失败对业务的影响是什么

这是我们需要提出的关键问题,它将推动我们解决如何处理这个问题,因为我们有许多不同难度的选择。

当然还有关于回忆、猜测和道歉的 Pat Helland 。

简短版:两位将军告诉我们,如果两条信息必须一致,那么我们需要将两条信息写在同一个地方。“不变量”限制了我们的数据模型。

您描述的不变量实际上是几个集合验证问题:“成员资格”集合只允许用户 A 的这么多成员,而组 B 的成员也只有这么多。如果你真的处于“我们会倒闭,如果这些规则被违反”的情况,那么你不能分发该集合的成员——你必须在修改它时锁定整个集合,以确保规则没有被破坏并且第一个作者获胜。

在您的建模中需要注意的一个元素:域模型是成员权限吗?还是“现实世界”负责成员资格,而域模型只是缓存该信息以供以后使用?您要非常小心地尝试在现实世界中强制执行不变量。

您最终可能会过度限制模型接受信息的顺序。


推荐阅读