目录
定义
聚合类是实体的升级,是由一组与生俱来就密切相关实体和值对象组合而成的,这整个组合的最上层实体就是聚合。Aggregate(聚合)是一组相关对象的集合,作为一个整体被外界访问,聚合根(Aggregate Root)是这个聚合的根节点。
引入聚合的目的是通过合理的对象边界控制对象之间的关系,在边界内保证对象的一致性与完整性,在边界外作为一个整体参与业务行为的协作。
最佳实践
1.如何划分聚合的边界?
-
【不变量与一致性】聚合暗含了一致性边界,在一致性边界之内建模真正的不变条件,代表了领域逻辑中的业务规则约束和事务一致性。在边界之外使用最终一致性,思考业务可接受的不一致时间。从业务约束的深入分析中,我们有可能会突破对一致性边界的既有认知,就能够设计出小聚合。
-
【完整性与独立性】推荐设计小聚合,好的做法是使用根实体来表示聚合,只包含最小数量的属性或值对象属性,那些与其他属性保持一致的属性。从经验来看,大量的聚合都可以建模成单个实体(根实体)。过分的小聚合,危害也大。完整性与独立性之间的平衡?聚合是否足够完整,聚合中的实体是否会被调用者单独调用。完整性除了通过聚合内部来保证,也可以通过聚合之间的关系来保证。
-
【质量的约束】判定为一个聚合整体,需要估算聚合成本,包括聚合内部的对象数量,对性能和内存消耗的影响等,业界对此也有新的解法。
2.聚合的行为原则
-
由聚合根统一对外提供履行该领域概念职责的行为方法,实现内部各个对象之间的行为协作。只有聚合根才是访问聚合边界的唯一入口。注意对于读写分离来讲,读场景可以直接跳过聚合来读取其对象,如按订单项的统计等。
3.聚合的协作
-
关联关系。通过唯一标识引用其他聚合,而不是直接的对象引用,此时关联的聚合是不会被即时加载的,不必担心性能问题。
-
依赖关系。一个聚合作为另一个聚合方法的参数,形成职责的委派。
不好案例
1.臃肿的聚合,开发人员引入的错误的不变条件,设计出庞大的聚合根,时常出现事务失败、性能或可伸缩性问题。不要包含不必要的属性,尤其是为了展示查询类场景需要。
2.某个用例需要修改多个聚合实例,将多个聚合组合起来搞个大聚合。需要带着批判态度来看,挑战假设,往往通过聚合间的最终一致性来实现,要思考可能接受的更新延迟时间。
3.聚合根内直接依赖资源库或外部服务。聚合根内直接复用上游上下文的领域对象。