DDD浅析

DDD(Domain Driven Design)在04年由著名建模专家eric evans发表的他最具影响力的书籍:《domain-driven design –tackling complexity in the heart of software》(中文译名:领域驱动设计—软件核心复杂性应对之道)一书中提出了“领域驱动设计(简称 ddd)”的概念,但是这么多年一直不温不火,最近几年为什么又开始火起来了呢?这里就要从历史上的软件危机开始说起。

历史软件危机

下图是从60年代至今的出现软件危机。
DDD浅析_第1张图片

第一次软件危机

60年代之前一直是汇编语言的天下,但是我们都知道汇编语言写起来巨慢无比,很难工业化,所以在60-70年代,面向过程语言出现来解决了这个问题,比如最经典的C语言,现在很多操作系统还是用C语言来编写。

第二次软件危机

80年代后,随着硬件的发展和面向过程语言出现后,大型软件也应用而生,但是面向过程型语言在大型软件上是很难维护的,比如我们知道的Java的JVM,就用C++来编写的,这个时候面向对象语言和设计模式的诞生解决这个问题。

第三次软件危机

2000之后,互联网热潮到来,需求的多样化,对三高场景的要求下,面向对象型语言和设计模式也无法解决这个痛点,这个时候,微服务到来解决这个问题,目前我们知道,90%的互联网企业都是微服务。

第四次软件危机

2015年之后,互联网热潮退化,回归到需求本身,而需求本身的变化越来越快,“小步快跑,快速迭代试错”的敏捷迭代下,系统越来越难维护,每个公司发展的一定阶段都会遇到这个问题,那么是什么来解决这个问题呢?有人说是DDD,我们接下来分析一下DDD到底能否解决这个问题。

问题和痛点

服务或者系统大多数的坏味道都有以下几点:

  • 一个字段变化导致从Mapper改到Controller
  • 一个商品需求的变化导致订单、结算等都要跟着变化
  • 基础域的一个模型的变化导致商品、订单、结算都要改造
  • 订单表字段很多,修改评价的逻辑却影响了订单的核心逻辑

归根就地的原因是过度耦合。

出现这些问题的本质原因

很多系统出现上面的问题无外乎下面几个原因:

  • 小步快跑,快速迭代试错
  • 业务日益复杂,需求迅速变化
  • 贫血模型导致逻辑分散到很多地方
  • 设计阶段总是考虑存储
  • 小范围重构
  • 技术能力参差不齐

那么,这些问题的本质原因是什么呢?实际上就是领域划分不清晰,如果我们的领域足够清晰,各司其职,高内聚低耦合,那么上面的这些原因是无法导致我们的系统逐渐变的难以维护的。

DDD是否能解决这个问题

我们先不着急说结论,先看一下DDD的过程。
DDD浅析_第2张图片
DDD的过程大概分成五步:

  1. PM、RD、CTO根据业务需求划分出初步的领域和限界上下文,以及上下文之间的关系,这里的CTO的角色就是我们常说的领域专家。
  2. 根据分析出的限界上下文来进行子域划分。
  3. 事件风暴进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;
  4. 为聚合根设计仓储,并思考实体或值对象的创建方式;
  5. 在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并进行重构。

这个过程,第一、二步是战略设计,后面三步就是落地的战术设计。

战略设计-限界上下文关系设计

下图是一个普通电商平台的领域上下文设计。

战略设计-子域划分

DDD浅析_第3张图片

战术设计-事件风暴的过程

DDD浅析_第4张图片
不同的聚合直接交互是通过聚合根中来交互,传入的数据是值对象,最终达到的效果是收敛变化,暴露不变。

术语

到这里,我们看出DDD的一些术语。

术语 含义
领域 领域是一个组织所做的事情以及其中包括的一切,比如电商平台
子域 当一个领域非常大时理解子域的概念,必须和核心域对应起来,子域也是领域的一部分,只不过它的重要性没有核心域那么大,它们之间的关系,你可以看作是人体器官中,心脏和其他器官的关系,在《领域驱动设计》中,其实并没有子域的概念,而是通用子域(Common Subdomain),而在《实现领域驱动设计》中,作者把子域拆分成了支撑子域(Generic Subdomain)和通用子域(Common Subdomain)
通用子域 变化比较小,通用性很强的领域,在整个业务下使用比如商品领域,在一个领域下,用户是很少变化的
支撑子域 变化比较小,只在某一些场景下会使用,比如用户领域
核心子域 变化比较大,只在某一些场景下会使用,比如订单领域
聚合 聚合是多个模型单元间的组合,它定义了模型的关系和边界,它有聚合根、实体、值对象组成,比如订单就是一个聚合
聚合根 访问聚合的唯一凭证,一般是业务编号,比如订单的订单号
实体 实体与面向对象中的概念类似,在这里再次提出是因为它是领域模型的基本元素。在领域模型中,实体应该具有唯一的标识符,从设计的一开始就应该考虑实体,决定是否建立一个实体也是十分重要的。
值对象 值对象和我们说的编程中数值类型的变量是不同的,它仅仅是没有唯一标识符的实体,比如有两个收获地址的信息完全一样,那它就是值对象,并不是实体。值对象在领域模型中是可以被共享的,他们应该是“不可变的”(只读的),当有其他地方需要用到值对象时,可以将它的副本作为参数传递。
领域服务 一个领域的接口服务,不是指一个微服务,是指一个微服务的接口
领域事件 事件消息发出的领域对象
防腐层 防腐层在DDD里是很重要的,服务内部是否变坏,很大一部分的功劳是防腐层赋予的。

战术设计-服务落地

DDD浅析_第5张图片

DDD防腐层的转换器设计

详看: https://blog.csdn.net/feigeswjtu/article/details/122562207

DDD的本质

DDD的设计写完了,那么我们再回过来看它的本质是什么呢?一个词: “以不变应万变”,不变是领域对外封装变化,对内允许变化。

你可能感兴趣的:(DDD,架构设计,DDD,架构设计)