领域驱动设计(DDD)

领域驱动设计--轻理论、列概念、重实践

Posted by jinyinzhubao on May 10, 2020

领域驱动设计(DDD):软件核心复杂性的应对之道! —— Eric Evans

关于领域驱动设计(DDD),网上有很多教程,详细而专业,足够从入门到精通;本文主要是结合自己所学,进行了核心知识点的梳理和对自己理解的记录,希望做到 轻理论、列概念、重实践

一、领域驱动设计的定义

关于领域驱动设计的定义,可以参见维基百科的解读。简单来说,DDD主要想达到这个目的:

DDD通过建立一个【业务域】到【软件域】的通用模型,把问题空间同解决方案空间联系在一起,真正把领域的知识挖掘出来,让领域专家可以去驱动软件的实现
事实上,

二、领域驱动设计的过程

DDD本质上是一种思维方式,而并不是一种设计模式。这种思维方式需要贯穿软件开发的整个生命周期,包括从需求到设计、开发、测试、重构。整个过程如下图所示,是一个涵盖了整个软件开发生命周期并且循环迭代的过程。

大体上,DDD分为战略建模战术建模,下面分别简单的介绍以下这两个阶段,同时列出相关概念点。

2.1 战略建模

战略建模阶段主要需要考虑问题域和解系统两个方面,基于软件是对现实世界的映射和模拟,将现实世界的问题或需求,映射为系统架构中的限界上下文

问题域方面:针对问题域,引入限界上下文(Bounded Context)和上下文映射(Context Map)对问题域进行合理的分解,识别出核心领域(Core Domain)与子领域(SubDomain),并确定领域的边界以及它们之间的关系,维持模型的完整性。 解系统方面:通过分层架构来隔离关注点,尤其是将领域实现独立出来,可以更利于领域模型的单一性与稳定性;引入六边形架构清晰地表达领域与技术基础设施的边界;CQRS模式则分离了查询场景和命令场景,针对不同场景选择使用同步或异步操作,提高架构的低延迟性与高并发能力。

举个实际中的例子,比如需要实现一个订单系统。

2.1.1 我们对限界上下文的领域划分如下图:

限界上下文示意图

2.1.2 整体上对订单及相关领域划分完之后,我们继续深入对官网购买生成订单这个领域的限界上下文进行划分,举例如下图:

2.1.3 进一步的,我们更深入的梳理、分析上下文之间的映射关系,这里列出相关概念,方便查询:

  • 合作关系(Partnership, PS):两个上下文紧密合作的关系,一荣俱荣,一损俱损。
  • 共享内核(Shared Kernel, SK):两个上下文依赖部分共享的模型。
  • 客户方-供应方开发(Customer-Supplier Development, CD):上下文之间有组织的上下游依赖。
  • 遵奉者(Conformist):下游上下文只能盲目依赖上游上下文。
  • 防腐层(Anticorruption Layer, ACL):一个上下文通过一些适配和转换与另一个上下文交互。
  • 开放主机服务(Open Host Service, OHS):定义一种协议来让其他上下文来对本上下文进行访问。
  • 发布语言(Published Language, PL):通常与OHS一起使用,用于定义开放主机的协议。
  • 大泥球(Big Ball of Mud, BBM):混杂在一起的上下文关系,边界不清晰。
  • 另谋他路(SeparateWay):两个完全没有任何联系的上下文。

领域驱动设计上下文映射关系图

结合上面的概念进行简单的解读:

  1. 对于上面划分的5大领域,它们之间存在着“共生”的关系,需要协同运作,所以使用PS(合作关系)进行描述
  2. D、U分别表示了业务领域的上下游关系
  3. ACL表示防腐层,在我们实际开发的时候,往往会写一个adapter或者converter,进行上下文隔离和转换
  4. OHS表示开放主机服务,作为订单在支付这个业务环节的下游

经过了上面这三步的领域分析、划分之后,划清了业务边界。这么做具有很多明显的优点:方便业务方与开发方之间的沟通;开发工程师可以分别聚焦于自己负责的细分开发领域;上下文之间的开发工程师可以方便的进行任务划分、边界确认、开发对接;解耦了各个业务上下文,高内聚、低耦合的系统(业务)架构由此开始,上下文的耦合度仅限于数据层面的耦合。

2.2 战术建模