取法其上,得乎其中

领域驱动设计是什么?能做什么?由什么构成?

什么是DDD?它的作用是什么?怎样构成?

DDD(领域驱动设计)是一套完整而系统化的一套设计方法论,主要针对高度复杂的软件系统,试图分离其复杂性,以解决软件难以理解、难以迭代的问题。

DDD主要分为两大块:
其一是战略设计:主要从业务视角出发,使得设计思路更加清晰、设计过程更加规范。
其二是战术设计:主要从技术视角出发,侧重于对模型进行实现

那么基本的设计流程是怎么样的呢?

  1. (战略)获取行为需求,搞清楚这个项目究竟有哪些需求
  2. (战略)领域建模,怎么样对这个项目进行抽象、设计
  3. (战术)架构设计,将抽象出来的模型进行落地
  4. (战术)数据库设计、代码实现

博文主要记录前三步。

如何获取行为需求?(事件风暴)

传统软件开发最常见的捕获用户需求的方式是基于“用户样例”的思路,即根据各个场景、行为流程。起初在《领域驱动设计》这本书里并没有规定捕获行为需求的具体方法,直到后面一位DDD专家Alberto提出了“事件风暴”的方法。

除此之外还有四色建模法。

有什么优点?其一是简单,其二是充分体现了DDD中沟通协作、统一语言的要点。

其中沟通协作的主要体现是在事件风暴中要求业务人员、技术人员,或者产品经理等都要一起协作进行,可以很大程度的避免了考虑不全面,亦或者从技术角度考虑业务是无法实现的等..一类问题。

而统一语言主要是在这个阶段达成对某些动名词的共识,最终做到消除歧义。

那么具体怎么做呢。

第一步,识别领域事件,我们要找到业务流程汇总发生了哪些事情。
第二步,识别命令,进一步说明是什么角色做了什么操作导致上述的事情发生。
第三步,识别领域名词,从领域事件和命令中找到“名词性概念”(名词大概率代表着业务中某个实体)。

识别领域事件

什么是领域事件?即在一个业务流程中每个步骤引发的结果,比如电商系统中的“订单已提交”、“商品已签收”,这些都是领域事件,并且名称一般是完成时态+被动时态。

为什么是从结果进行梳理需求呢?因为事件风暴的作者认为,从结果入手要比从操作入手更容易把业务想清楚。

搞清楚了这些,就可以各个人员将自己想到的领域事件去写下来,然后再逐个进行:统一名词、查漏补缺,然后再剔除非主业务流程的事件。这种先发散、后收敛,反复迭代的过程实际上就是一种头脑风暴。

此外要注意的两点:

  1. 技术事件不是领域事件,比如事务已回滚、缓存已命中,不是领域事件不在这个阶段讨论。
  2. 查询功能不是领域事件,领域事件应该是对某样事物产生了影响,比如创建、修改、删除。

识别命令

什么是命令?即引发领域事件的操作,是谁执行的命令?为了执行命令需要什么数据?本质来说是为了充实领域事件的概念。

识别领域名词

领域名词本质来讲就是指在领域事件中设计到的名词,比如“订单已提交”、“订单已取消”,那么可以捕捉到“订单”这个实体的存在。而这些名词就是领域建模的主要素材。

识别到领域名词其后,把围绕同一个名词的命令、事件、执行者、查询数据摆在一起,最后形成好几堆。

最后

于是最终出现的领域名词就很可能是领域对象了,但是有的名词可能需要合并或拆解后才是一个合理的领域对象。

然后将一个个领域名词之间的关系,诸如:一对一、一对多,以这些逻辑就可以产生领域模型。

如何进行领域建模

首先要将各个领域划分为一个个的子域,而分解的标准在于能够支持一个完整的业务流程,保证这个业务流程所涉及到的领域都在一个“限界上下文”之中。同时,一个子域可以包含另外一个或多个子域,如此以保证业务流程完整。

等等,什么是“限界上下文”?其英文表达是 bounded context,本质来讲就是限制某个领域的一个实体的表达语义。

为什么要这样呢?有两个原因:

  1. 统一语言
  2. 降低认知负载

正如电商领域的商品一样,在销售阶段它是商品,在运输阶段则变成了货物,但实际上它们是一个东西。但是我们在一个单一领域进行开发的时候,我们要确定下来这个界限,它在这里就一定是某物,消除二义性。

领域的核心思想就是将问题域逐级细分,来降低业务理解和系统实现的复杂度。

其中领域共分为三种类型:

  1. 核心域,主要代表当前系统的主要业务构成的领域。
  2. 通用域,主要是被其他一个或多个子域使用的领域。
  3. 支撑域,既不包含主要的业务,也不包含通用功能的子域。

遵循以上,就可以将各个领域划分出来。除此之外的好处就是,限界上下文作为领域边界之外亦可以成为指导微服务系统拆分的依据。

如何落地抽象的模型

当各个领域划分清楚后,就要为各个领域进行落地了,在DDD中属于“战术设计”。

领域内部的结构由:聚合组成。
聚合由实体和值对象组成。

下面依次展开解释。

实体

本质上是拥有唯一标识、状态,且具有生命周期的业务对象。比如商城系统中的“商品”、“用户”就属于实体的概念。而领域模型中的实体概念中除了涉及到属性,还要包括操作、行为(业务逻辑)。而对于包含信息的多少,则归类为四种类型:

  • 失血模型,仅包含数据定义的getter/setter方法,业务逻辑放在服务层中
  • 贫血模型,包含了一些业务逻辑,但不包括依赖持久层的业务逻辑
  • 充血模型,包括了所有的业务逻辑,且包括依赖于持久层的业务逻辑
  • 胀血模型,除了充血模型的内容以外还持有与业务逻辑不相关的应用逻辑(如授权、事务等)

值对象

没有唯一标识、状态、生命周期的一个不可修改的对象,主要为了辅助描述实体中的属性。比如“用户实体”中需要存储它的家庭住址,而家庭住址分别有:国家省市区..几个属性,这个时候单独把这些属性单独抽象为“地址实体”,然后作为属性进行存储,如此就属于值对象。

聚合(聚合根)

聚合主要是把一组在业务上共同协作进行业务逻辑的实体包含在一起进行完成一个整体的业务逻辑的封装结构。

而通过协作各个实体然后达成整体的业务逻辑的这个结构称之为“聚合根”。

聚合和领域的区别

一个领域含有一个或多个聚合,在领域一层可以协作多个聚合进行完成任务。

领域驱动设计是什么?能做什么?由什么构成?

https://ku-m.cn/index.php/archives/821/

作者

KuM

发布时间

2024-03-10

许可协议

CC BY 4.0

添加新评论