IT2.0业务中台规划牵引客户IT基础设施投资随想 (十):基于DDD的业务对象颗粒度定义
前两节介绍了业务对象的内涵,以及与之相应的业务对象建模基本方法,介绍了识别业务对象的流程、基本方法和原则。
然而,在实际识别和定义业务对象过程中,业务对象的颗粒度却是最难以确定“好”和“坏”标准,而这又会影响到以业务对象为宿主的业务应用服务的拆分颗粒度。换句话说,拆分业务应用服务的目的都是为了实现业务对象的“高聚合、松耦合”,即如下图所示,同一业务对象的业务处理逻辑变得更加集中,更易于数据的同源管控,其内部业务逻辑变化不会对服务消费方产生直接影响,也就是只有实现了“高聚合”,才能“松耦合”。
BUT,从利用业务应用服务快速搭建新业务模式的业务应用的角度出发,我们会非常希望业务对象尽可能“松耦合”,而且理论上越是“松耦合”、“细粒度”的业务对象,其业务应用服务支撑的前台应用场景越是灵活多样。总结一下,一方面只有业务对象“高聚合”才能“松耦合”,另一方面又希望业务对象能够“松耦合”并“拆分成更细粒度”。这就是业务对象及其业务应用服务拆分很难的原因,其本质是“业务对象的处理逻辑能更加集中”与“业务对象本身能更加分散”之间的矛盾,从业务视角来看,前者代表着集中管控类的诉求,后者代表着快速发展、构建、演进类的诉求。
对于集中管控来说,希望管辖范围内的每一个个体都是符合管控逻辑的,也即是对业务对象有很强的一致性要求,要求业务对象内部遵循统一的一致性原则。对于快速发展、构建、演进来说,则是希望可复用、去中心化和分布式,要求业务对象对外提供的服务尽可能单一、简单,彼此之间有很清晰的边界。因此,这个本质上可以说是强一致性和柔性一致的矛盾,对于任何业务对象来说,都需要考虑到这两方面的诉求,相关要求可以参考数据库技术中的ACID和BASE策略。
ACID:
- 事务的原子性(Atomicity)是指一个事务要么全部执行,要么不执行
- 事务的一致性(Consistency)是指事务的运行并不改变数据库中数据的一致性
- 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态
- 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚
BASE:
- Basically Available基本可用,大部分数据在大部门时间是可用的
- Soft state软状态,状态可能有一段时间没有被更新
- Eventually consistent最终一致性,异步拷贝的数据最终都是一致的
为了在上述两个目的之间取得平衡,在定义业务对象颗粒度的时候,需要坚持两方面的要求。一方面需要坚持其一致性底线,简单来说就是业务对象不可再分拆了,再拆就很难保证业务集中管控的一致性要求了。另一方面需要尽可能将业务对象拆分得更有利于高复用性,让业务对象涉及的业务能力尽可能简单明了,不要让其承载的业务过于复杂,而不利于该业务最大范围和频次地被调用。
要按照上述要求进行设计,比较好的方法是DDD,即领域驱动设计(Domain-driven design)。首先,我们需要先理解DDD中的聚合、聚合根这两个概念。聚合,它通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成。聚合定义了一组具有内聚关系的相关对象的集合,我们把聚合看作是一个修改数据的最小原子单元。聚合根,每个聚合都有一个根对象,根对象管理聚合内的其他子对象(实体、值对象);聚合之间的交互都是通过聚合根来交互,不能绕过聚合根去直接和聚合下的子实体进行交互。
在下面的例子中,Car、Wheel、Position、Tire四个对象构成一个聚合,其中Car是聚合根;Customer也是聚合根,Customer不能直接访问Car下的Tire(子实体),而是只能通过聚合根Car来访问。
(图片来自互联网)
( 上述定义表达了一个关于聚合的一致性设计原则,如下图所示:聚合内的数据修改,是ACID强一致性的,对一致性业务规则的遵从是较强的;跨聚合的数据修改,是BASE最终一致性的,对一致性业务规则的遵从是较弱的。遵守这些原则,可以让我们最大化的降低并发冲突,从而最大化的提高整个系统的吞吐。
(图片来自互联网)
对于DDD领域驱动设计来说,最核心的就是要建立一个领域模型,通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,聚合定义了一组具有内聚关系的相关对象的集合。这种聚合间的边界本质上就是一致性边界,即聚合不可再分,否则就很难保证其业务强一致性要求;聚合也不可再合并,否则对聚合之间的弱一致性业务规则要求也会造成损害。如果将聚合作为领域模型中一个个较为独立的“高聚合”和“松耦合”业务对象的话,恰好能够在“业务集中管控”和“业务高可复用”之间取得平衡,将其作为对业务对象颗粒度定义的基本要求是非常合适的。
在DDD领域驱动设计的基本定义中,聚合作为业务对象,每个聚合都有一个根和一个边界,边界定义了一个聚合内部有哪些实体或值对象,根是聚合内的某个实体:
- 实体:实体就是领域中需要唯一标识的领域概念,实体的范围决定了领域的范围。
- 值对象:用程序的方式来表达就是,如果两个对象的所有的属性的值都相同我们会认为它们是同一个对象的话,那么我们就可以把这种对象设计为值对象。
- 服务:领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物。这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象共同完成这个操作或动作。
关于上述定义的具体表现形式,可以参考下图的示例。
(图片来自互联网)
DDD领域驱动设计的元模型可以参考下图,这里就不做详细介绍了,大家可以参考相关的材料。
(图片来自互联网)
本节重点介绍了业务对象颗粒度定义这一重要问题如何通过DDD领域驱动设计的方法来解决的,在实际设计过程中,要处理好聚合之间的一致性边界,非常需要业务一致性管控规则的输入。需要特别说明的是,这些业务规则并非一成不变的,因此,业务对象的颗粒度定义会随着业务规则的调整而不断迭代、演进,由此也会让以业务对象为宿主的业务应用服务和数据服务不断迭代、演进。
- 点赞
- 收藏
- 关注作者
评论(0)