DDD概念
DDD概念
DDD概念
什么是DDD
ddd(Domain driven design)领域驱动设计,是一种用于切割软件中界限上下文的软件设计方法
好处
- 可以延长软件的寿命
- 使得软件架构更加清晰,更方便程序员理解
- 可以使得面试官眼前一亮,更好找工作(开玩笑的)
坏处
- 使得数据交互会点混乱
- 前期设计的时间更长
充血模型
充血对象
将业务层中的对对象的数据操作提取到对象之中,如订单时间更新,信息字符串拼接,等对对象的操作放进对象之中,而不是在业务层里面写(这个业务层写了,另一个别人写的业务层不知道你写了,那么就会导致数据出错)
充血包
类似的,将对该包里面的操作放到包里面,这样就不会造成操作的散落
领域
领域就是一个模块(如支付领域/模块,订单领域/模块,库存管理领域/模块),包含了完成某个功能的所有需要的东西,这个就是领域,
类似充血对象和充血包,即该领域包含了完成一件事情的所有东西,一般对应微服务架构中的一个微服务,
领域设计符合面向对象原则的单一职责原则和开闭原则等,即一个领域只干一类事情,然后对接口开发,对修改关闭
类似的一个电商系统,里面的支付功能可以视为一个领域,该领域内可以完成支付功能所需要的所有东西和流程
领域对象
- 即一个领域里面应该有什么对象
实体对象
实体对象对应着操作的实体,包括改实体的属性,对实体的操作
例子: 一部小车是一个实体,这个实体包括小车的颜色,重量,百公里加速度,品牌,还包括对改小车的操作,如挂挡,加油,刹车,打开后备箱等
值对象
值对象是描述实体的属性的对象,值对象是不可以更改的
即 值对象是描述值的对象
例子:颜色是小车的属性,那么值对象即为颜色,值对象的值就可以为红色,蓝色绿色等
聚合
聚合对象是对多个实体对象的组合,
例子:订单就是一个聚合对象,里面包括用户实体对象,商品实体对象等
基础设施层
仓储
仓储就是用来存储数据的持久化对象,类似持久化对象po(persistent object)
网络接口
网络接口用来对网络中的各种请求提供接口,从而保持领域服务层的干净
网络请求如http,rpc,redis等
领域编排
通过领域编排,我们可以将不同的领域串在一起,从而可以实现一个完整的业务流程,
如超市领域,加油站领域,家领域,如我从家领域出发到加油站领域加油再到超时领域完成家里人安排的购买任务,这个就是领域编排
触发器
如果系统没有那么复杂,就几个领域,那么我们可以使用触发器来进行我们的业务流程,如定时任务,用户下单,登录时间过期等条件触发器
DDD建模方法
界限上下文
界限上下文就是领域的边界
四色建模(风暴模型)
四色建模是一种用于区分领域的界限上下文的建模方法,可以使用四色建模来划分出一个一个的领域及领域对象,
即四色建模是划分领域的或者设计领域的一种方法
步骤
在DDD中,我们的流程是这样的
- 寻找领域事件,即找出可能产生的结果
- 根据可能产生的结果,寻找导致这个结果的原因,即为领域时间寻找决策命令
- 通过行为命令提取需要的领域对象(对应的实体,值对象等)
- 决策命令使用领域对象经过一系列的业务流程
- 完成一系列的行为事件
- 而行为事件就可能用到基础设施层中的仓储和网络适配器等外部接口
四色建模就是一一找出上面高亮的几个东西
举例
我们现在有这样一个场景,我们现在要根据家里人的命令去超市买东西,我需要使用购物车去把东西放进去,走了一圈又一圈把东西买好,有些东西还要打标(称重量等),有些东西还要去找店员装配好,在这个过程中我还可以去叼一颗糖在嘴里
:::info
那么在这个例子中,
- 行为命令:买东西
- 领域:超市
- 领域对象:购物车(实体),要买的物品(实体)等,购物车的颜色大小(值对象),糖果(实体)
- 业务流程:装东西进购物车,打标,装配等
- 外部接口:打标时,需要用到的秤(显示重量),和打标时的打标机(打印出标上的信息)
:::
从上面可以看出,我们在执行业务流程的时候,不单单可以调用领域中的对象,还可以调用其他领域对象,如糖果
我们还可以有其他的领域,如加油站,幼儿园,学校等,通过领域编排,我们可以将这些领域串联在一起,形成完整的一条领域流程
六边形架构
工程结构(注意注释即可)
.
├── README.md
├── docs
│ ├── dev-ops
│ │ ├── environment
│ │ │ └── environment-docker-compose.yml
│ │ ├── siege.sh
│ │ └── skywalking
│ │ └── skywalking-docker-compose.yml
│ ├── doc.md
│ ├── sql
│ │ └── road-map.sql
│ └── xfg-frame-ddd.drawio
├── pom.xml
├── xfg-frame-api (主要定义对外部的接口和对外部的统一响应结果)
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── cn
│ │ └── bugstack
│ │ └── xfg
│ │ └── frame
│ │ └── api
│ │ ├── IAccountService.java
│ │ ├── IRuleService.java
│ │ ├── model
│ │ │ ├── request
│ │ │ │ └── DecisionMatterRequest.java
│ │ │ └── response
│ │ │ └── DecisionMatterResponse.java
│ │ └── package-info.java
│ └── xfg-frame-api.iml
├── xfg-frame-app (和应用相关,如config,启动类,配置文件等)
│ ├── Dockerfile
│ ├── build.sh
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── bin
│ │ │ │ ├── start.sh
│ │ │ │ └── stop.sh
│ │ │ ├── java
│ │ │ │ └── cn
│ │ │ │ └── bugstack
│ │ │ │ └── xfg
│ │ │ │ └── frame
│ │ │ │ ├── Application.java
│ │ │ │ ├── aop
│ │ │ │ │ ├── RateLimiterAop.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── config
│ │ │ │ ├── RateLimiterAopConfig.java
│ │ │ │ ├── RateLimiterAopConfigProperties.java
│ │ │ │ ├── ThreadPoolConfig.java
│ │ │ │ ├── ThreadPoolConfigProperties.java
│ │ │ │ └── package-info.java
│ │ │ └── resources
│ │ │ ├── application-dev.yml
│ │ │ ├── application-prod.yml
│ │ │ ├── application-test.yml
│ │ │ ├── application.yml
│ │ │ ├── logback-spring.xml
│ │ │ └── mybatis
│ │ │ ├── config
│ │ │ │ └── mybatis-config.xml
│ │ │ └── mapper
│ │ │ ├── RuleTreeNodeLine_Mapper.xml
│ │ │ ├── RuleTreeNode_Mapper.xml
│ │ │ └── RuleTree_Mapper.xml
│ │ └── test
│ │ └── java
│ │ └── cn
│ │ └── bugstack
│ │ └── xfg
│ │ └── frame
│ │ └── test
│ │ └── ApiTest.java
│ └── xfg-frame-app.iml
├── xfg-frame-domain (存放一个一个的领域)
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── cn
│ │ └── bugstack
│ │ └── xfg
│ │ └── frame
│ │ └── domain
│ │ ├── order (这是一个领域)
│ │ │ ├── model (这里存放的是领域对象)
│ │ │ │ ├── aggregates (聚合对象)
│ │ │ │ │ └── OrderAggregate.java
│ │ │ │ ├── entity (实体对象)
│ │ │ │ │ ├── OrderItemEntity.java
│ │ │ │ │ └── ProductEntity.java
│ │ │ │ ├── package-info.java
│ │ │ │ └── valobj (值对象)
│ │ │ │ ├── OrderIdVO.java
│ │ │ │ ├── ProductDescriptionVO.java
│ │ │ │ └── ProductNameVO.java
│ │ │ ├── adapter (定义适配器,适配器里面有port和repository,并且都是定义的接口,没有实现类,实现由基础设施层来实现)
│ │ │ │ ├── port
│ │ │ │ └── repository
│ │ │ └── service (存放业务类)
│ │ │ ├── OrderService.java
│ └── xfg-frame-domain.iml
├── xfg-frame-infrastructure
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── cn
│ │ └── bugstack
│ │ └── xfg
│ │ └── frame
│ │ └── infrastructure (基础设施层,主要负责对外部的交互)
│ │ ├── dao (存放与数据库交互的dao类)
│ │ │ ├── IUserDao.java
│ │ │ ├── RuleTreeDao.java
│ │ │ ├── RuleTreeNodeDao.java
│ │ │ └── RuleTreeNodeLineDao.java
│ │ ├── po (存放持久化po对象)
│ │ │ ├── RuleTreeNodeLinePO.java
│ │ │ ├── RuleTreeNodePO.java
│ │ │ ├── RuleTreePO.java
│ │ │ └── UserPO.java
│ │ └── adapter (存放适配器的实现类)
│ │ ├── port (port的实现类)
│ │ └── repository (仓储的实现类)
│ └── xfg-frame-infrastructure.iml
├── xfg-frame-trigger (可以触发领域的东西放在这里面)
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── cn
│ │ └── bugstack
│ │ └── xfg
│ │ └── frame
│ │ └── trigger
│ │ ├── http (controller触发器)
│ │ │ ├── Controller.java
│ │ │ └── package-info.java
│ │ ├── mq (mq消息触发)
│ │ │ └── package-info.java
│ │ ├── rpc (rpc)
│ │ │ ├── AccountService.java
│ │ │ ├── RuleService.java
│ │ │ └── package-info.java
│ │ └── task (存放定时任务)
│ │ └── package-info.java
│ └── xfg-frame-trigger.iml
└── xfg-frame-types (存放业务无关的常用类型)
├── pom.xml
├── src
│ └── main
│ └── java
│ └── cn
│ └── bugstack
│ └── xfg
│ └── frame
│ └── types
│ ├── Constants.java
│ ├── Response.java
│ └── package-info.java
└── xfg-frame-types.iml
更新: 2025-08-09 13:38:00
原文: https://www.yuque.com/duifangzhengzaishuru-rqbua/axyc58/em4cubw664rdhipo