领域驱动设计之聚合与聚合根
对实体与值对象等进行关联设计后,就应该进行聚合的划分以及聚合根的确定。
首先我们需要明确为什么需要进行聚合的划分?
原来我们的系统对领域划分的最小单位通常是模块,比如客户信息管理模块、雇员信息管理模块。但模块的划分对于设计来说,还是显得粒度太粗。
一.聚合与聚合根
1.定义了对象之间清晰的关系和边界,并实现领域模型的内聚。我的理解是:一个聚合内的对象才具有强关联,对象的关联设计应该是针对一个聚合中的实体与实体或实体与值对象之间。(比如一个下订单的领域中,订单(实体)、订单项(实体)以及订单状态(值对象)应该为一个聚合,订单与订单项有关联、订单与订单状态有关联)。
2.必须将聚合作为一个修改数据的单元。
3.一个聚合必须有一个聚合根,根是聚合中的一个实体,通常聚合中其他实体需要依赖于聚合根,其他实体不能没有聚合根而单独存在,从业务的角度来看它是没有单独存在的意义的。比如在第1点中,订单应该是聚合根,因为订单项与订单状态两个对象在没有订单的情况下是没有意义的。
4.对一个聚合中实体的访问或操作,必须通过这个聚合的聚合根开始,主要的目的是这样可以保证不变的一致性规则。比如在第1点中,订单有一个订单总额属性,订单项有一个当前项金额的属性,有一个规则是订单总额为订单项总额之和,如果其他聚合绕过订单聚合根而直接操作订单项实体,则操作后,很难保证不变的一致性规则,如果通过订单聚合根操作订单项,而订单聚合根负责业务规则的一致性,这样就能够保证了。所以聚合根的一个重要职责是负责维护本聚合内部的一致性。
5.在对聚合进行查询或操作时,整个聚合是作为一个整体,不能直接查询聚合内部某个非根的对象。
二.识别聚合
识别聚合经过理论和实际的项目开发,我认为应该从以下几个方面进行聚合划分
1.哪些实体或值对象在一起才能够有效的表达一个领域概念。
2.对象之间是否必须保持一些固定的规则。
3.聚合不要设计太大,否则会有性能问题以及业务规则一致性的问题。
4.聚合中的实体和值对象应该具有相同的生命周期,并应该属于一个业务场景。
三.识别聚合根
1.一个聚合只有一个聚合根,聚合根是可以独立存在的,聚合中其他实体或值对象依赖与聚合根。
2.只有聚合根才能被外部访问到,聚合根维护聚合的内部一致性。