领域驱动设计-Domain-Driven-Design
一、Evans DDD 是什么
1.1 背景
- 2002年,敏捷宣言诞生
- 时代处于 CS 到 BS 的转换时期
- 2003年 Eric Evans 发表<领域驱动设计>领域驱动设计>
- 2013年 微服务诞生,微服务的拆分和边界限定成为了难点,因而DDD思想开始重新发挥作用
1.2 描述
- 2003 Eric Evans : Domain-Driven Design - Tackling Complexity in the heart of Software 领域驱动设计
- 领域建模是一种艺术的技术
- 面向对象建模方法,是一种工程方法论
- 是用来解决大型复杂软件快速应付变化的解决之道
- 属于业务架构设计范畴
- 使系统有较好的一致性和良好的扩展性
1.3 重要性
- 没有领域模型,只靠代码编写,复杂的领域需求会使得他们无法交流讨论,使工作陷入泥沼
- 有少许领域模型,没有维护好模型和代码之间的联系,两者产生差异,无法实现
1.4 存在的问题
- 自身概念复杂,学习难度大,门槛高
- 国内实践少,参考少,尝试成本高
- 敏捷迭代,使得项目放弃了建模
二、为什么使用MDD/DDD
2.1 MDD 模型驱动设计
2.2 MDD = DDD+DSL(领域特定语言)
2.3 优点
- 真正快速开发
- 更具成本优势
- 引导质量提高
- 很少出错
- 不在乎人事变动
- 授权领域专家
- 能够让高级程序员专攻难关
- 让业务和IT之间架设了桥梁
- 减少业务需求带来的影响面
- 导致技术对变化不是太敏感
- 增强架构
- 可以截获领域知识
-
能够关注业务而不是技术
-
架构发展阶段
- 单体
- MVC
- SSM
- 分层
- DDD分层
- 对称性分层
三、软件开发本质
3.1 问题空间
-
需求、用例、业务分析
- 领域问题:一个特定边界内的业务需求总和
3.2 解决方案空间
-
模型、组件、架构、设计实现
- 领域模型:是业务功能场景在软件系统的映射转化
3.3 映射转化
四、分析设计发展阶段
4.1 主要阶段
-
围绕数据库的驱动设计
- 设计从数据库表设计开始
-
面向对象的分析设计
- 区分分析和设计阶段,两个阶段是比较割裂的
-
融合了分析和设计阶段的领域驱动设计
4.2 不同阶段局限性
-
传统数据库方式的局限性
-
分析方面
- 不能迅速有效全面分析需求
-
设计方面
- 导致过程化设计编程,丧失了面向对象设计的特点,对象仅成为数据的载体
-
运行方面
- 导致软件运行时负载集中在数据库端,难于扩展
-
其他
-
对象与关系型数据库的天然阻抗
- 库表关系不能真正还原对象之间的联系,需要额外字段
- CRUD的操作,不能直观标识对对象的意图
- 数据模型和关系模型存在偏差
-
-
-
面向对象:分析和设计割的局限性
- 分析人员负责从问题空间领域汲取需求,即从需求领域着手
- 设计人员:剥离出能够通过编程构建的组件,组件间能够有效运作,解决应用程序的问题
- 迭代的需求,不能很好的分析,由设计人员按照数据的逻辑进行拼凑
- 两个阶段目标不一致,导致割裂,项目失败
4.3 DDD领域模型特点
-
统一语言/通用语言
- 项目中统一交流的语言,提高交流效率、工作效率、避免理解错误与误解、沟通低效
- 让应用能和业务相匹配,通过在业务与代码中的技术之间采用共同的语言达成的
-
统一领域模型
- 只有业务,没有技术
- 表达需求真实世界的模型,和软件技术无关
- 通过分层,将领域模型层突出,其他为辅助
五、分层架构
5.1 分层详情
-
表现层
- 与MVC的V类似,关注显示和用户指令
-
应用层
- 与MVC的C类似,指挥领域对象实现功能,精简
-
领域层
- 核心业务概念
-
基础支撑层
- 与MVC的M类似,与软件技术相关
5.2 分层架构优点
- 不同层级,能够保证高内聚低耦合,有利于程序分布式部署、提升心梗、高可伸缩性
六、DDD实施的注意点
6.1 挖掘核心深层模型
6.2 剔除反面通用子域
6.3 内聚机制
6.4 隔离核心
6.5 领域模型切割
6.6 行为型设计模式
- 模板方法
- 策略
- 状态
- 命令
- 迭代器
- 备忘录
- 观察者
- 中介者
- 访问者
- 责任链
- 解释器
七、领域模型元素
7.1 实体
- 拥有业务含义的全局唯一标识符,拥有生命周期,且标识符在经历软件系统的各种状态,生命周期后仍能保持一致
7.2 值对象
- 一般来说不需要有业务含义的唯一标识符,因为我们并不关心它是谁
- 值对象和实体是整体
- 值对象是不变的,可共享
-
值对象复制
- Java clone
7.3 服务
- 行为接口
7.4 领域对象生命周期
7.5 聚合
-
一组相关联的对象,出于数据变化的目的,将它们视为一个单元
- 汽车中:轮胎+车架+座椅
- 汽车中:引擎
- 汽车中:驾驶员+乘客
-
聚合中的不变性
- 划出不变性和可变部分
7.6 工厂
-
工厂用来封装对象创建所必需的知识,它们对创建聚合特别有用
- 抽象工厂
- 工厂方法
-
属于领域层
7.7 组合
- Hibernate O/R Mapping框架,实现对象的创建和组合
7.8 客户端只关心模型,而不是数据存储,存储和访问都交给Repository完成,避免数据库规范扰乱模型的整洁
限界上下文
- 确定语义所在的领域边界,边界定义了模型的适用范围,使团队所有成员能够明确地知道什么应该在模型中实现,不应该在模型中实现
7.9 4种Robbin领域模型
-
失血模式-不提倡
- POJO 仅有Getter/Setter方法
- 业务逻辑和应用逻辑,都在应用层
-
贫血模式
- 部分业务逻辑放在domain object中
-
充血模式
- 大部分业务逻辑放在domain object中
-
胀血模式-不提倡
- 过多业务逻辑放在domain object中
-
实体本之行为放入实体,行为跨越实体本身生命周期的,可放入服务中
八、领域服务
8.1 对一个聚合的操作,放在一个单独的接口中
8.2 CRUD是服务吗
- 管理行为,是服务
8.3 领域层服务
- 与业务有关,CRUD
8.4 应用层服务
- 与软件设计有关,类似MVC中的Controller
8.5 基础层服务
- 发送Email
九、领域事件
9.1 对聚合的操作,建成一系列离散事件
9.2 在不同场景下,由实体发出事件驱动服务,通过类似异步消息机制实现松耦合
9.3 业务规则 Specification
- JPA进行条件筛选的时候,有Specification+仓储(Repository)的结合
十、事件风暴
10.1 构建领域模型的充满乐趣的实施方法
10.2 领域时间与架构设计的本质
- 领域事件
10.3 事件风暴步骤
- 头脑风暴
- 罗列领域事件
- 领域事件集合
- 标注事件命令
- 标注时间命令发起方角色
- 领域故事分析
- 提取领域对象
- 领域对象与代码模型映射
- 代码落地
十一、CQRS框架
11.1 命令与查询分析,数据查询与业务操作分离
11.2 是DDD开发风格下对领域模型按机构的一种简化改造
11.3 DDD+CQRS使用六边形对称性架构
11.4 DDD+CQRS+Event Souring 是有趣且强大的技术
十二、JiveJdon框架
12.1 JiveJdon 3.0是按照2004年国外最新设计思想”领域驱动设计”(Domain-Driven Design 简称DDD)、基于JdonFramework自主开发的复杂软件系统
12.2 开源
12.3 性能优异、可伸缩性强
12.4 可拓展性
12.5 采用组件动态设计的面向构件架构
十三、微服务框架
13.1 微服务的特征
- 通过服务进行组件化
- 围绕业务能力组织
- 去中心化的治理技术
- 去中心化的管理数据
- 基础设施自动化
- 容错和演进式设计
13.2 设计微服务的路径依赖困境
- 利用拆分单体服务思维,拆分子模块,形成微服务,不可行
13.3 基于微服务的重构
- 识别领域对象
- 界定上下文边界
- 使用聚合概念把关联性强的业务划分在同一个边界下
- 限定聚合和聚合之间通过聚合根来访问
- 结合业务限定上下文与技术因素,对服务的粒度、分层、边界划分、依赖关系、集成关系进行梳理
- 构建通用语言,高效沟通
13.4 微服务设计方法
- 事件风暴
- 领域对象以及服务矩阵和代码设计
- 领域对象以及服务矩阵
13.5 代码结构模型
- application
- domain
- infrastruture
- interface
13.6 微服务是技术实现和部署的范畴,实现领域或中台的业务逻辑,为前台应用提供服务
十四、分层架构
14.1 MVC框架改造
- 限定上下文,将一个大领域拆分成独立的子域
- 针对领域对象,添加领域层,提供服务
- 用用层,组装各个领域服务,对外提供能力
- 应用层验证、领域服务验证、领域模型验证
14.2 四层架构
14.3 五层架构
14.4 六边形架构
- 洋葱架构
十五、更多大厂实践
15.1 阿里盒马
15.2 阿里文娱
15.3 美团外卖
- 点评业务
- 供应链业务
15.4 业务中台
- 中台的本质是提炼各个业务条线的共同需求,并将这些功能打造成组件化产品,然后以 API 接口的形式提供给前台各业务部门使用
- 从限定上下文到微服务,从应用架构到技术架构
- 从决策到接口
- 从领域模型到分层架构
- 从DDD 到TDD