1.4 DDD

领域驱动设计(Domain Driven Design,DDD)是Eric Evans于2003年提出的一种设计方式,其特点是实现了在需求分析、软件设计方面的一体化,形成领域模型就可以指导“类”设计的软件架构模型,几乎仅通过一个过程就直接完成了业务架构和应用架构的设计。

DDD最经典的概念图如图1-7、图1-8所示。

图1-7 六边形架构示意图

顾名思义,DDD侧重于从“领域”出发考虑问题,而且这个“领域”也不同于传统企业架构理论中范围较大的“领域”概念,其限界上下文涵盖的范围可能非常小,因此可能有多个“领域”都存在同名不同义的实体。这个特点在图1-8中表现得非常明显。

图1-8 领域模型示例

DDD领域的另一位大师Vaughn Vernon在《领域驱动设计精粹》一书中介绍了“保单”的例子。这个例子在承保、审核、理赔三个限界上下文中分别定义了“保单”实体,每个实体都有重复的部分和差异的部分。这么做是因为他认为整合“保单”概念会创造一个过于臃肿的“超负荷”的实体。这样的实体也许大家在设计过程中也曾经遇到过,一个数据实体包含了过多的属性,导致数据设计不能很好地分离“关注点”。

此外,从与工程方法结合的角度看,Eric Evans曾提出DDD方法主要面向敏捷过程,二者在方法层面有相似之处,都强调快速由需求进入开发过程,也都注重对模式的运用。但实际上让DDD大放光彩的是微服务,因为微服务在落地实践中非常需要一个能够有效指导服务划分的方法论。

Chris Richardson在《微服务架构设计模式》一书中专门介绍了DDD在微服务设计中的应用方式,还给出了一个通过DDD处理服务设计问题的例子——对“上帝类”的拆分。“上帝类”作为全局类,可以被多个不同领域的应用调用,因而也就设计了包含不同领域的状态和行为的复杂结构,比如书中提到的“订单”。下单、送餐、付款等多个领域都会触发订单状态的转换,如果将丰富的行为打包成一个中央订单数据库,会导致微服务设计出现紧耦合,微服务之间不够独立;如果只保留一个纯数据服务的订单服务,又会成为“贫血模型”。这个问题的解决方案就是采用DDD的设计理念,在不同领域定义同名不同义的订单并形成不同的服务。

Vaughn Vernon和Chris Richardson所举的这两个例子其实体现了DDD不同于传统企业架构理论的处理方式。传统企业架构理论希望实现企业级的数据模型定义,即在企业范围内尽可能消除同名不同义的数据实体,所以保单和订单在传统企业架构理论中通常会被处理为一个而非多个实体。那么在解决数据模型中有些实体过于庞大的问题时,传统数据模型还是要依靠对业务对象的识别以及对数据实体业务含义的明确,因为采用DDD方式完全按照领域的拆分本身也存在弊端,企业级数据查询与应用十分困难,这时需要通过全局统一编号等方式来追踪本质上是同一个业务对象的不同实体在不同领域间的状态变化过程。

对于保单的例子,由于没有更多的信息,因此笔者无法进行详细的比较,但是在传统企业架构理论的数据建模中,子类的概念也能满足需要;对于订单的例子,在传统企业架构理论中,很可能不会将其设计成一个庞大的订单实体,而是会将其拆分成客户、地址、付款单等多个数据实体。

但是在订单例子中,传统企业架构理论确实有可能会朝着设计一个中央订单数据库的方向前进,因为很可能将订单定义为一个订单业务能力组件,供各类业务应用调用,这是企业级业务能力复用的一种体现。至于紧耦合的问题,也许并不是订单服务变动会引起其他服务变动,而是在其他服务需要修改订单模式时,会引起订单服务变动。因此,紧耦合的问题我们要辩证地看,即在集中设计订单业务能力组件获得的好处和引起的耦合之间进行取舍。

总体而言,DDD更像是一个业务架构设计方法,而非企业架构设计。并且,Vaughn Vernon也认为企业级的架构是无法从顶层直接设计的,只能在领域建模完成后逐个进行尝试性融合。Eric Evans也在其书的结尾对总体规划方法表达了一种委婉的不信任。但是,DDD方法毕竟涉及业务架构设计,并且目前互联网企业也有吸收其理念进行业务架构设计的成功案例,因此了解DDD方法的优点并加以运用,对提升传统企业架构理论的设计效率,尤其是在更好地对接应用架构设计方面,还是很有价值的。

此外,也有一些实践者尝试通过在现有DDD方法的基础上补充企业层面分析,或者将DDD分析与企业架构分析进行关系映射,补充DDD的企业级分析能力,提升DDD方法的应用范围。这些尝试对于DDD而言是一种提升,笔者也期待有更多的改进能够出现。