DDD-9- 聚合划分
1、定义
将实体和值对象划分为聚合并围绕聚合定义边界
选择一个实体作为聚合根,并仅允许外部对象持有对聚合根的引用
作为一个整体来定义聚合的属性和不变量,并把执行责任赋予聚合根或者指定的框架机制
2、特性
具有整体与部分的关系
第二,具有不变规则,而且这种不变规则在并发的时候可能被破坏
3、作用
提升了对象系统的粒度
保障业务完整性
减少出错概率
每个聚合都会形成保证事务一致性的边界
事务边界由商业动机决定,因为任何时候都是业务来决定对象集的有效状态应该是什么
4、划分原则
事务一致性
只能在一次事务中修改一个聚合实例并提交
生命周期一致性
是指聚合边界内的对象,和聚合根之间存在“人身依附”关系。
即:如果聚合根消失,聚合内的其他元素都应该同时消失
问题域一致
事实上问题域一致是限界上下文(Bounded Context)的约束
聚合作为一种战术模式,所表示的模型一定会位于同一个限界上下文之内
场景频率一致
经常被同时操作的对象,它们往往属于同一个聚合。而那些极少被同时关注的对象,一般不应该划为一个聚合
操作场景不一致的对象,或者说如果一个对象在不同场景下都会被使用,应该考虑把它们分到不同的聚合中
小聚合
5、经验法则
在聚合边界内保护业务规则不变性
聚合要设计的小巧
整体部分只是聚合的特征之一,还需要考虑小聚合,事务边界一致性(业务级别的)
聚合包含大量实体的情况,拆分成多个小聚合
每个聚合可以更容易地实现,更容易测试
使用最终一致性更新其他聚合
6、关键点
业务规则才是驱动力,最终决定在单次事务完成提交后,哪些对象必须是完整、完全和一致的驱动力
7、设计步骤
聚合要设计得小巧
每个聚合一开始创建时只允许包含一个实体,并且它将作为聚合根
聚合边界内保护业务不变性规则
在上一步中,已经声明了至少在单个实体持久化时所有内在字段/属性必须是最新的
但是现在需要一个一个地检查每个聚合。
在检查聚合 A1 时,问问领域专家需不需要更新其他已定义的聚合,来响应聚合 A1 发生的改变
为每个聚合和它的一致性规则制作一个清单,还要记录所有这些基于响应的更新的时间范围
换句话说,“聚合 A1”作为清单的标题,如果其他的聚合类型也需要更新来响应 A1 的变化,就把它们罗列在 A1 之下
现在询问领域专家,每个基于响应的更新可以等待多长时间
对每一个即时发生的时间范围(3a),应该坚定地考虑把这两个实体合并到同一个聚合的边界之内。
对于每一个在给定等待时间(3b)内更新的响应聚合,则遵循最小化聚合原则:“利用最终一致性更新其他聚合”。
8、辅助理解
聚合是对象之间的关系
在聚合内部使用对象导航,跨聚合则使用 ID 导航
为了确保不变规则不被破坏,总的原则是:聚合外部对象对非聚合根对象只能读,不能写,必须通过聚合根才能对非根对象进行访问
因为聚合的不变规则往往不是单个对象能够处理的。比如说,“同一技能不能录入两次”这个规则,通过查看单独的技能对象是无法验证的,必须查看员工的全部技能,才能判断一条新技能是否重复。所以这种规则必须由聚合根或者相应的领域服务负责验证。
评论