DDD领域驱动相关知识和总结

领域模型

领域:用来确定范围的,范围即边界,领域就是这个边界内要解决的业务问题域

子域:领域进一步划分为子领域。每个子域对应一个更小的问题域和业务范围。根据自身重要性和功能属性划分为三类子域 - 通用域:被多个子域使用的通用功能。认证,权限 - 核心域:产品和公司核心竞争力功能。 - 支撑域:非产品和公司核心竞争力功能,也不包含通用功能子域,具有启用特性。数据字典

通用语言:在事件风暴过程中,通过团队交流达成共识,能够简单,清晰,准确描述业务含义和规则的语言

事件风暴建立通用语言到领域对象设计和代码落地过程

  1. 事件风暴
  2. 领域故事分析
  3. 提取领域对象(通过表格记录对象和属性)
  4. 领域对象与代码模型映射
  5. 代码落地

界限上下文,界限是领域边界,上下文是语义环境。用来封装通用语言和领域对象,提供上下文环境,保证领域之内一些术语,业务相关对象有确切的含义,没有二异性

商业模式的不同,不同场景导致核心域的划分不同。

领域建模和微服务建设的过程和方法基本类似,其核心思想就是将问题域逐步分解,降低业务理解和系统实现的复杂度

实体和值对象

实体和值对象是组成领域模型的基础单元

实体

拥有唯一标识符,且标识符在历经各种状态变更后仍能保持一致。

值对象

通过对象属性值识别对象,将多个相关属性组合为一个概念整体。本质上是一个集。值对象不可变。

DDD引入值对象希望从领域模型设计出发,而不是先设计数据模型,减少数据库表数量和表之间复杂依赖关系,简化数据库设计,提高数据库性能

实体对象和值对象在不同场景下,会设计出不同结果。例:收货地址由于经常修改,作为实体对象。

聚合和聚合根

聚合

领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性

聚合在DDD分层架构里属于领域层,领域层包含了多个聚合,共同实现核心业务逻辑。聚合内实体以充血模型实现个体业务能力,以及业务逻辑的高内聚

聚合根

避免由于复杂数据模型缺少统一业务规则控制,导致数据不一致。

如果把聚合比作组织,那聚合根就是这个组织的负责人。聚合根也称为根实体,它不仅是实体,还是聚合的管理者

聚合之间,对外接口都以聚合根ID为关联接受外部任务和请求。

聚合根选择

是否独立生命周期,是否全局唯一id;是否可创建,修改其他对象;是否专门模块管理实体

聚合构建流程

  1. 事件风暴梳理出所有实体和值对象
  2. 找出聚合根
  3. 根据业务单一职责和高内聚原则,找出与聚合根管理紧密实体和值对象
  4. 根据聚合根和实体,值对象,画出引用和依赖模型
  5. 根据业务语义和上下文划分多个聚合到同一个界限上下文

聚合的一些设计原则

领域事件

用来表示领域中发生的事件。领域事件将导致进一步业务操作,实现业务解耦同时,有助于形成完整业务闭环

一次事务最多只能更改一个聚合的状态。如果一次业务设计多个聚合状态修改,应采取领域事件最终一致性

微服务内领域事件,发送方聚合将事件发布到事件总线,订阅方接收事件数据完成后续业务操作 微服务外领域事件,通过引入分布式事务来解决数据一致性

领域事件处理

事件构建和发布:事件唯一标识,发布时间,事件类型,事件源以及业务属性;通过应用服务或领域服务发布事件总线或消息中间件;也可事件表定时轮询,数据库日志获取增量事件

事件数据持久化:本地业务数据库事件表中。共享事件数据库中,需保证分布式事务数据一致性

事件总线:服务外事件表保存,异步发送消息中间件;服务内直接分发

消息中间件:市面上 中间件产品,MQ,Kafka

事件接收和处理

DDD四层结构

严格分层架构

服务逐层对外封装,组合,依赖关系清晰,一层引用一层

松散分层架构

依赖关系比较复杂,难管理,允许跨层调用;容易是核心业务逻辑外泄

微服务架构的演进

可以聚合为基础单元,完成领域模型和微服务架构的演进。聚合可以作为一个整体,在不同的领域模型之间重组或者拆分,或者直接将一个聚合独立为微服务

微服务内服务的演进

在微服务内部,实体的方法被领域服务组合和封装,领域服务又被应用服务组合和封装

三层结构和DDD结构区别

常见微服务架构

整洁架构

整洁架构最主要的原则是依赖原则,它定义了各层的依赖关系,越往里依赖越低,代码级别越高,越是核心能力

六边形架构

应用是通过端口与外部进行交互的

不管是DDD还是整洁还是六边形都考虑了前端需求的变领域模型的不变

中台本质上是领域的子域,它可能是核心域,也可能是通用域或支撑域。通常大家认为阿里的中台对应 DDD 的通用域,将通用的公共能力沉淀为中台,对外提供通用共享服务。

项目级微服务

与前端应用集成,一起完成特定业务;通常遵循分层架构。核心逻辑在应用层完成,通过API网关为前台提供服务,前后端分离;微服务之间集成通常在应用层

企业级中台微服务

某个职责单一中台微服务,企业级业务流程需将多个这样微服务组合起来才能完成

通过在中台微服务上增加一层,例如BFF来完成跨微服务服务组合和编排

BFF 微服务与其它微服务存在较大的差异,就是它没有领域模型,因此这个微服务内也不会有领域层。BFF 微服务可以承担应用层和用户接口层的主要职能,完成各个中台微服务的服务组合和编排,可以适配不同前端和渠道的要求

中台

中台的关键词:共享、联通、融合和创新,快速响应能力和企业级的无缝联通和融合能力

阿里业务中台的前身是共享平台,而原来的共享平台更多的被当作资源团队,他们承接各业务方的需求,并为业务方在基础服务上做定制开发。 阿里业务中台的目标是把核心服务链路(会员、商品、交易、营销、店铺、资金结算等)整体当作一个平台产品来做,为前端业务提供的是业务解决方案,而不是彼此独立的系统

业务中台的建设可采用领域驱动设计方法,通过领域建模,将可复用的公共能力从各个单体剥离,沉淀并组合,采用微服务架构模式,建设成为可共享的通用能力中台。

中台建模流程

  1. 按照业务流程或功能属性,集合,将业务域细分为多个中台;根据功能属性和重要性归类核心中台或通用中台
  2. 选取中台,根据用例,业务场景完成事件风暴,找出实体,聚合和限界上下文。依次建立领域模型
  3. 以主领域模型为基础,扫描其他领域模型,检查是否存在重复或重组领域对象,提炼重构主领域模型,形成最终领域模型设计
  4. 完成所有主领域模型对比,重构
  5. 根据模型完成微服务设计

中台业务模型构建

事件风暴

- 产品愿景:对产品顶层价值设计,业务范围,目标用户,核心价值和愿景,与其他同类产品差异和优势
- 业务场景分析,从**用户视角,根据业务流程和用户旅程**,采用**用例和场景**,探索典型场景,找出**领域事件,实体和命令等领域对象**,支撑领域建模,尽量遍历所有**业务细节**,充分发表意见
- 领域建模:根据领域对象,分析**实体**之间**依赖关系**组成聚合,划定上下文,建立模型及模型间依赖
- 微服务拆分和设计:将领域模型作为微服务拆分一个重要依据。同时考虑敏态和稳态业务分离,弹性伸缩,安全性,技术异构等非业务因素。

微服务代码模型

微服务一级目录结构

按照DDD分层架构职责定义

用户接口层

应用层

领域层

基础层

聚合之间的代码边界一定要清晰;一定要有代码分层的概念

整理领域对象,将其整理到表格

并思考:

典型的领域模型

代码结构

边界

演进式架构就是以支持增量的、非破坏的变更作为第一原则,同时支持在应用程序结构层面的多维度变化

微服务的过度拆分会使软件维护成本上升,若微服务内部的逻辑和代码边界很清晰,你就可以随时根据需要,拆分出新的微服务,实现微服务的架构演进

逻辑边界

同一业务领域或应用内紧密关联的对象所组成的不同聚类的组合之间的边界

业务端以聚合为单位进行业务能力的重组,在微服务端以聚合的代码目录为单位进行微服务代码的重组。 按照 DDD 方法设计的微服务逻辑边界清晰,业务高内聚,聚合之间代码松耦合,因此在领域模型和微服务代码重构时,我们就不需要花费太多的时间和精力了

物理边界

部署和运行的视角来定义微服务之间的边界

代码边界

用于微服务内的不同职能代码之间的隔离

数据对象视图

数据持久化对象 PO(Persistent Object),与数据库结构一一映射,是数据持久化过程中的数据载体。 领域对象 DO(Domain Object),微服务运行时的实体,是核心业务的载体。 数据传输对象 DTO(Data Transfer Object),用于前端与应用层或者微服务之间的数据组装和传输,是应用之间数据传输的载体。 视图对象 VO(View Object),用于封装展示层指定页面或组件的数据

微前端

前端设计时我们需要遵循单一职责和复用原则,按照领域模型和微服务边界,将前端页面进行拆分。 同时构建多个可以独立部署、完全自治、松耦合的页面组合,其中每个组合只负责特定业务单元的 UI 元素和功能,这些页面组合就是微前端

前端项目团队只需要完成企业级前端主页面与业务单元的融合,前端只关注前端主页面与微前端页面之间的集成

战略设计

战略设计是根据用户旅程分析,找出领域对象和聚合根,对实体和值对象进行聚类组成聚合,划分限界上下文,建立领域模型的过程

如图

战术设计

梳理微服务内的领域对象,梳理领域对象之间的关系,确定它们在代码模型和分层架构中的位置,建立领域模型与微服务模型的映射关系,以及服务之间的依赖关系

微服务的演进策略

绞杀者策略

逐步剥离业务能力,用微服务逐步替代原有单体系统的策略

修缮者策略

在现有系统的基础上,剥离影响整体业务的部分功能,独立为微服务,比如高性能要求的功能,代码质量不高或者版本发布频率不一致的功能

微服务设计原则

要领域驱动设计,而不是数据驱动设计,也不是界面驱动设计

要边界清晰的微服务,而不是泥球小单体。

要职能清晰的分层,而不是什么都放的大箩筐。

要做自己能 hold 住的微服务,而不是过度拆分的微服务