关于 ddd-aggregate
用于应用领域驱动设计聚合模式的技能,帮助建模者围绕事务不变量划分实体,并确定根实体访问及引用规则。
主要功能
- 01划分聚合边界并确定根实体
- 02在事务中维护不变量
- 03仅通过 ID 引用其他聚合
- 04评估聚合大小与事务范围
适用场景
- 01判断哪些实体应一起变更
- 02选择对象引用还是 ID 引用
- 03排查锁竞争或事务过大
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-aggregate安装后在 Claude Code 中输入/ddd-aggregate确认已加载。
详细介绍
一句话概述
聚合是一组实体和值对象,它们作为一个整体处理数据变更——是一个事务一致性边界,由一个拥有它们的根实体构成。
何时使用此技能
- 判断哪些实体应作为一个整体归属在一起。
- 在“一个大对象”和“多个相关对象”之间做选择。
- 引用规则:“
Order应持有Customer对象,还是只持有customerId?” - 追溯到聚合大小的性能和锁定问题。
何时不使用此技能
- 单个实体的行为——这属于
ddd-entity的范畴。 - 跨上下文关系 →
ddd-context-mapping。 - 通过事件实现聚合间的最终一致性 →
ddd-domain-event。
核心内容
聚合有一个根实体。外部代码只能持有根的引用。聚合内部的对象可以自由地相互引用。其他聚合只能通过 ID 引用,绝不能通过对象引用。
在一个聚合内,不变量以同步、事务性的方式强制执行。如果某条规则必须始终在两个实体之间成立,那么这两个实体就属于同一个聚合。如果规则允许延迟满足(可以接受最终一致性),那么这些实体可以属于不同的聚合,并通过领域事件协调。
一个事务只涉及一个聚合。 这是规范性规则。在一个事务中加载并修改两个聚合是一种不良迹象——这通常意味着聚合边界划分有误,或者应该将工作拆分为命令和事件驱动的后续处理。
聚合根是唯一的入口点。聚合外部的代码调用根的方法;根根据需要将操作委托给内部实体。根负责确保每次操作后聚合的不变量都成立。
决策启发
- 优先选择小型聚合,而不是大型聚合。无法确定时,就拆分。
- 如果两个实体不需要在同一事务中变更,它们就属于不同的聚合。
- 如果两个实体共享一个必须始终同步成立的不变量,它们就属于同一个聚合。
- 其他聚合只能通过 ID 引用。在
Order中持有Customer对象引用会迫使系统急切加载,并带来事务处理难题。
反模式
- 包含领域模型半数内容的上帝聚合——每次变更都会加载整个世界,锁竞争加剧,数据库事务不断膨胀。
- 跨聚合对象引用——将半个模型加载到内存中,并使持久化关系变得错综复杂。
- 通过传递根对象让调用方遍历其子对象,从而访问聚合内部。
- 使用“每个实体一个仓储”,而不是“每个聚合根一个仓储”——这会向调用方暴露聚合内部。
另请参阅
ddd-entity— 实体是构成聚合的基本单元。ddd-value-object— 值对象可以自由嵌套在聚合中。ddd-repository— 每个聚合根对应一个仓储。ddd-domain-event— 聚合间一致性通过事件实现。ddd-anti-patterns— 上帝聚合和跨聚合引用。
参考资料
- Evans,Domain-Driven Design(2003),第 6 章(领域对象的生命周期)。
评论
支持 Markdown