domain-driven-design - 单个命令是否应该处理多个聚合?
问题描述
在 CQRS 和 DDD 中,聚合是事务边界。因此,我一直以这样一种方式对命令进行建模,即每个命令总是只针对单个聚合。当然,从技术上讲,可以编写一个处理多个聚合的命令处理程序,但这不会在单个事务中,因此不会是一致的。
如果您实际上必须处理多个聚合,我通常会使用流程管理器,但这有时会让人感觉开销很大。此外,据我了解,流程管理器始终只对域事件做出反应,而不是直接由命令处理。因此,您需要决定将起点放在哪个聚合上。
我已经看到有些人使用所谓的域或应用程序服务来解决这个问题,它们也可以接收命令,然后在多个聚合上工作——但在这种情况下,流程的事务性质会丢失。
举一个简单的例子,更好地说明场景:
- 用户应加入一个组。
- 一个用户有最大数量的组。
- 一个组有最大数量的用户。
在哪里放置触发初始加入过程的命令,以及调用它的什么?user.join(group)
感觉是对还是错group.welcome(user)
。我可能会选择第一个,因为它更接近于无处不在的语言,但无论如何……</p>
如果我有一些高于聚合的东西,比如前面提到的服务,那么我可以运行一些东西,比如:
userManagement.addUserToGroup(user, group);
然而,这个addUserToGroup
函数随后需要调用这两个命令,这反过来意味着它必须处理正在处理的两个命令——这与拥有单独的聚合和将聚合作为事务边界有些违反直觉。
对此进行建模的正确方法是什么?
解决方案
可能值得在最终一致性和集合验证上查看 Greg Young 。
失败对业务的影响是什么
这是我们需要提出的关键问题,它将推动我们解决如何处理这个问题,因为我们有许多不同难度的选择。
当然还有关于回忆、猜测和道歉的 Pat Helland 。
简短版:两位将军告诉我们,如果两条信息必须一致,那么我们需要将两条信息写在同一个地方。“不变量”限制了我们的数据模型。
您描述的不变量实际上是几个集合验证问题:“成员资格”集合只允许用户 A 的这么多成员,而组 B 的成员也只有这么多。如果你真的处于“我们会倒闭,如果这些规则被违反”的情况,那么你不能分发该集合的成员——你必须在修改它时锁定整个集合,以确保规则没有被破坏并且第一个作者获胜。
在您的建模中需要注意的一个元素:域模型是成员权限吗?还是“现实世界”负责成员资格,而域模型只是缓存该信息以供以后使用?您要非常小心地尝试在现实世界中强制执行不变量。
您最终可能会过度限制模型接受信息的顺序。
推荐阅读
- python - 即使“templates/”在同一目录中,Flask 也会引发“TemplateNotFound”
- python - 循环和转换excel文件时无法分配给函数调用
- python - 尝试为 Flask 创建虚拟 Venv 时出现致命错误?
- javascript - @keyframes 动画只在第一次工作
- kubernetes - eksctl 创建集群卡住“等待 CloudFormation 堆栈”
- linux - Saving a directory name to a variable in linux
- java - android java - 如何在 Google Maps api 的折线中设置可见性 false 和 true?
- ios - 通过按钮将文本插入textView然后删除
- javascript - 身份验证后重定向到 Passport.js 中的上一页(不重复)Node.js
- reactjs - 在单个 setState 调用上多次响应状态更新