跳转至

领域驱动设计(Domain-Driven Design,DDD)与软件复杂度

领域驱动设计(DDD)旨在应对软件复杂度的挑战。那么,软件复杂度的成因是什么,又该如何应对?

软件复杂度的成因与应对方法

  • 规模 —— 通过分而治之控制规模
  • 结构 —— 通过边界保证清晰有序
  • 变化 —— 顺应变化方向

复杂系统的定义

"由大量相互作用的部分组成的系统。与整个系统比起来,这些组成部分相对简单,没有中央控制,组成部分之间也没有全局性的通信,并且组成部分的相互作用导致了复杂行为。"


软件复杂度的维度分析

要剖析软件系统的复杂度,就可以从理解能力与预测能力这两个维度探索软件复杂度的成因。

一、理解能力

维度 影响因素 具体表现 影响程度
规模 需求动态性 功能需求持续增加与演变
业务环境变化带来的适应性需求
功能复杂性 功能模块数量激增
业务逻辑交织导致的耦合性增强
设计质量失衡 设计不足:缺乏前瞻性扩展能力
过度设计:引入冗余架构复杂度
架构演化压力 分层架构的层级扩展需求
模块化设计的边界维护成本
协作成本上升 团队规模扩大导致的沟通复杂度
代码责任分配的协调难度
预测能力短板 对未来变化预估不足的被动应对
架构僵化引发的连锁重构风险
结构 系统组织方式 决定系统复杂度的关键因素 极高
变化 设计平衡 在设计不足与过度设计之间取得平衡的难度 极高

## DDD设计元模型分布表

空间类型 设计元模型 作用 重要性
问题空间 统一语言 描述需求问题 核心
核心子领域 分解问题空间,识别重要业务
通用子领域 分解问题空间,通用功能模块
支撑子领域 分解问题空间,支撑性功能
解空间 界限上下文 业务功能模块边界隔离
上下文映射 描述不同上下文间的关系
战略设计 高层架构设计指导
战术设计 具体实现模式指导

## 复杂度应对策略表

复杂度成因 应对方法 实施策略 预期效果
规模膨胀 分而治之 子域划分
模块化设计
降低单个模块复杂度
结构混乱 边界清晰 界限上下文
层次架构
提高系统可理解性
需求变化 顺应变化 领域建模
统一语言
增强系统适应性

DDD的核心思想

面向领域的思维方式,将要解决的业务概念和业务规则等内容提炼为领域知识,然后借由不同的建模范式将这些领域知识抽象为能够反映真实世界的领域模型。

关键概念

领域划分的原因

  1. 通过划分子域,来拆解问题域降低复杂度
  2. 识别不同子域的重要性,更好的实现资产的分配

界限上下文

是指某个业务或者功能模块的上下文,由于这个上下文是和其他业务隔离开的,所以叫界限上下文。

上下文映射

领域驱动设计中的一种模式,用于描述不同限界上下文之间的关系和交互。


问题空间与解空间

DDD架构图

软件世界也可一分为二,分为构成描述需求问题的真实世界与获取解决方案的理念世界。整个软件构建的过程,就是从真实世界映射到理念世界的过程。

构建软件(世界)也就是从真实世界中的问题空间寻找解决方案,将其映射为理念世界的解空间(solution space)来满足问题空间的需求。因此,软件系统的构建实则是对问题空间的求解,以获得构成解空间的设计方案。

映射关系图

重要原则

问题空间需要解空间来应对,解空间自然也不可脱离问题空间而单独存在。

对于客户提出的需求,要分清楚什么是问题,什么是解决方案,真正的需求才可能浮现出来。在看清了问题的真相之后,我们才能有据可依地寻找真正能解决问题的解决方案

软件构建过程中的需求分析,实际就是对问题空间的定位与探索。如果在问题空间还是一团迷雾的时候就贸然开始设计,带来的灾难性结果是可想而知的

徐锋认为,"要做好软件需求工作,业务驱动需求思想是核心。传统的需求分析是站在技术视角展开的,关注的是'方案级需求';而业务驱动的需求思想则是站在用户视角展开的,关注的是'问题级需求'。"

那种站在技术视角展开的需求分析,实际就是没有明确问题空间与解空间的界限。


DDD的设计元模型

领域驱动设计为问题空间与解空间提供了不同的设计元模型。

问题空间

强调运用**统一语言**来描述需求问题,利用**核心子领域**、**通用子领域**与**支撑子领域**来分解问题空间,如此就可以"揭示什么是重要的以及在何处付出努力"。

解空间

除去统一语言与子领域,其余设计元模型都将运用于解空间,指导解决方案围绕着"领域"这一核心开展业务系统的**战略设计**与**战术设计**。

问题空间与解空间对比表

维度 问题空间 解空间
关注点 业务问题和需求 技术解决方案
视角 用户视角 技术视角
内容 问题级需求 方案级需求
设计元素 统一语言、子领域 界限上下文、架构模式
目标 理解真实世界问题 构建技术实现方案
重要性 需求分析基础 系统设计依据

领域驱动设计控制软件复杂度的中心主要在于“领域”,Eric Evans就认为:“很多应用程序最主要的复杂度并不在技术上,而是来自领域本身、用户的活动或业务。

领域驱动设计战略设计阶段的核心模式是限界上下文,指导架构设计的核心模式是分层架构,前者决定了业务架构和应用架构,后者决定了技术架构。

识别限界上下文需要对业务需求和业务流程有着清晰的理解,建立领域模型需要的领域知识和概念也都来自于细粒度层次的业务需求,更不用说领域驱动设计本身就强调领域专家需要就领域知识与开发团队进行充分沟通。

领域驱动不足之处

  • 领域驱动设计缺乏 规范的统一过程 ,是其不足之一
  • 领域驱动设计缺乏 与之匹配的需求分析方法 ,是其不足之二
  • 领域驱动设计缺乏 规范化的、具有指导意义的架构体系 ,是其不足之三。
  • 领域驱动设计的领域建模方法 缺乏固化的指导方法 ,是其不足之四

领域驱动设计统一过程

/img/chapter_ddd/domain_process.png

全局分析阶段

该阶段主要通过对目标系统执行价值需求分析与业务需求分析这两个工作流,完全抛开对解决方案的思考与选择,仅仅从需求分析的角度以递进方式开展对问题空间的深入剖析。

/img/chapter_ddd/global_process.png

架构映射阶段

架构映射(architectural mapping)阶段根据全局分析阶段获得的产出物,即价值需求与业务需求,分别从组织级、业务级与系统级3个层次完成对问题空间的求解,映射为架构层面的解决方案。

/img/chapter_ddd/mapping.png

  • 组织级映射、
  • 业务级映射
  • 系统级映射