ddd说白了就是以前的service太乱太多了,把他们按照微服务的思想group by在了几个核心领域下
mapping的出生和essay的出生有关,但是之后的更新就和essay包括sentence都没关系了。ddd的核心就是把domain划分好,每个domain提供自己的能力,最外层的大逻辑放在application层
```Java
your-project/
├── interfaces
│ └── controller
│ ├── UserController.java
│ └── OrderController.java
│
├── application
│ └── service
│ ├── UserAppService.java
│ └── OrderAppService.java
│
├── domain
│ ├── entity
│ │ ├── User.java
│ │ └── Order.java
│ ├── repository
│ │ ├── UserRepository.java(接口)
│ │ └── OrderRepository.java(接口)
│ ├── service
│ │ └── UserDomainService.java(可选,纯业务逻辑)
│ └── event
│ └── OrderCreatedEvent.java
│
├── infrastructure
│ └── persistence
│ ├── mapper
│ │ ├── UserMapper.java
│ │ └── OrderMapper.java
│ └── repository
│ ├── UserRepositoryImpl.java(仓储接口实现)
│ └── OrderRepositoryImpl.java
│
├── config
├── scripts
├── tests
├── docs
└── README.md
```

## 贫血充血?
贫血模型:业务逻辑主要在服务层实现。就比如普通的`VO`和`DTO`,只是作为一个数据 bean,里面不会有太多动作
充血模型:业务逻辑主要在域对象内部实现,比如`ProductRoom`这种,类里面有很多业务动作
贫血模型:对象主要负责存储数据,类似于数据结构。
充血模型:对象不仅存储数据,还负责实现与之相关的业务逻辑。
## 分层
如果你将传统的**Controller-Service-Mapper**结构迁移到领域驱动设计(DDD)的一级目录体系下,可以按照以下方式映射:
---
### 一、Controller 放置到接口层(`interfaces`)
- 传统项目中的 `Controller` 通常负责接口暴露和请求处理,对应 DDD 中的**接口层**。
```Java
interfaces/
└── controller/
├── UserController.java
└── OrderController.java
```
职责说明:
- 接收前端请求、参数校验和转换。
- 调用应用服务层(application)提供的服务接口。
- 将结果封装为视图或响应对象返回给前端。
---
### 二、Service 放置到应用服务层(`application`)
- 传统项目的 `Service` 通常混合了业务逻辑和事务控制。在DDD中,它们被分为两部分:
- **应用服务层(Application Service)**(调用领域逻辑、事务管理)
- **领域服务(Domain Service)**(纯业务逻辑,与事务和外部技术无关)
但一般来说,传统项目中的大多数`Service`方法都应直接迁移到应用服务层:
```Java
application/
└── service/
├── UserAppService.java
└── OrderAppService.java
```
职责说明:
- 调用领域层(domain)的聚合根和领域服务。
- 控制事务(@Transactional)、权限控制等。
- 编排、协调不同领域逻辑或多个聚合的操作。
注意:如果发现某个 `Service` 中有大量业务逻辑,这些业务逻辑应提炼为领域服务或聚合方法,放置在`domain`层。
---
### 三、Mapper 放置到基础设施层(`infrastructure`)
- 传统项目的 `Mapper`(如MyBatis的mapper.xml和mapper接口)是具体的数据库访问实现,应归入基础设施层:
```Java
infrastructure/
└── persistence/
├── mapper/
│ ├── UserMapper.java
│ └── OrderMapper.java
└── repository/
├── UserRepositoryImpl.java
└── OrderRepositoryImpl.java
```
职责说明:
- 提供数据存取的具体实现(例如MyBatis、JPA)。
- 实现领域层定义的`Repository`接口。
- 数据持久化和数据访问的具体技术细节。
---
### 建议迁移步骤
- **识别核心业务**:将真正的业务逻辑提炼到`domain`层,保持纯净。
- **拆分Service**:
- 业务编排、事务、权限控制放在`application`。
- 纯业务逻辑放在`domain`。
- **封装数据访问**:
- mapper实现和ORM框架放到`infrastructure`。
- 使用领域定义的仓储接口进行解耦。
---
通过以上方式,传统三层架构能更自然地适应领域驱动设计的分层结构,实现更好的关注点分离和更清晰的项目结构。
## 通用语言
怎么理解通用语言这个概念呢?在事件风暴过程中,通过团队交流达成共识的,能够简单、清晰、准确描述业务涵义和规则的语言就是通用语言。也就是说,通用语言是团队统一的语言,不管你在团队中承担什么角色,在同一个领域的软件生命周期里都使用统一的语言进行交流。
比如商促、抽佣、优惠黑名单这些就是通用语言。我们现在==事件风暴==还不够规范,导致一些通用语言并没有对齐。
不过,一个好处是,在数字化工具中,通过工程的方式实现了下面的表格。

Here's the Markdown representation of the table in the image:
| 层 | 聚合 | 领域对象名称 | 领域类型 | 依赖的领域对象 | 包名 | 类名 |
| --- | --- | ---------- | ---- | ---------- | -------------------------------------- | ---------------------------------- |
| 应用层 | / | 创建请假信息应用服务 | 应用服务 | 创建请假信息领域服务 |.leave.application.service | CreateLeaveInfoAppService |
| 应用层 | / | 请假审批已通过 | 事件发布 | 请假审批(审核)|.leave.application.event.publish | SendApprovalEventInfo |
| 领域层 | 请假 | 请假单 | 聚合根 | |.leave.domain.leave.entity | Leave |
| 领域层 | 请假 | 创建请假信息 | 命令 | |.leave.domain.leave.entity | Leave |
| 领域层 | 请假 | 审批轨迹 | 值对象 | |.leave.domain.leave.entity | ApprovalTrace |
| 领域层 | 请假 | 创建审批轨迹信息 | 命令 | |.leave.domain.leave.entity | ApprovalTrace |
| 领域层 | 请假 | 创建请假信息 | 领域服务 | 创建请假信息 |.leave.domain.leave.service | CreateLeaveInfoDomService |
| 领域层 | 请假 | 创建审批轨迹信息 | 领域服务 | 创建审批轨迹信息 |.leave.domain.leave.service | CreateApprovalTraceDomService |
| 领域层 | 人员 | 人员 | 聚合根 | |.leave.domain.person.entity | Person |
| 领域层 | 人员 | 创建人员信息 | 命令 | |.leave.domain.person.entity | Person |
| 领域层 | 人员 | 组织关系 | 值对象 | |.leave.domain.person.entity | PersonRelationship |
| 领域层 | 人员 | 创建组织关系 | 命令 | |.leave.domain.person.entity | PersonRelationship |
| 领域层 | 人员 | 创建人员信息 | 领域服务 | 创建人员信息 |.leave.domain.person.service | CreatePersonInfoDomService |
| 领域层 | 人员 | 创建组织关系 | 领域服务 | 创建组织关系 |.leave.domain.person.service | CreatePersonRelationshipDomService |
| 基础层 | 请假 | 请假仓储接口 | 仓储接口 | |.domain.leave.repository.facade | LeaveRepositoryInterface |
| 基础层 | 请假 | 请假仓储实现 | 仓储实现 | |.domain.leave.repository.persistence | LeaveRepositoryImpl |
| 基础层 | 人员 | 人员仓储接口 | 仓储接口 | |.domain.person.repository.facade | PersonRepositoryInterface |
| 基础层 | 人员 | 人员仓储实现 | 仓储实现 | |.domain.person.repository.persistence | PersonRepositoryImpl |
| | | |
| --- | ----- | --------------------- |
| | 场景 | sentence + focus_word |
| | 文章 | essay |
| | | |
| | 词卡 | word_card |
| | 用户的翻译 | user_translation |
| | AI的翻译 | ai_translation |
## DDD课程大纲
### 开篇词
| 序号 | 标题 | 时长 |
|------|------|------|
| 1 | 开篇词 \| 学好了DDD,你能做什么?| 10:18 |
### 基础篇
| 序号 | 标题 | 我的理解 |
| --- | ------------------------ | ---------------------- |
| 01 | 领域驱动设计:微服务设计为什么要选择DDD?| |
| 02 | 领域、子域、核心域、通用域和支撑域:傻傻分不清?| |
| 03 | 限界上下文:定义领域边界的利器 | 一个限界上下文理论上就可以设计为一个微服务。|
| 04 | 实体和值对象:从领域模型的基础单元看系统设计 | |
| 05 | 聚合和聚合根:怎样设计聚合?| |
### 进阶篇
| 序号 | 标题 | 时长 |
|------|------|------|
| 06 | 领域事件:解耦微服务的关键 | 17:38 |
| 07 | DDD分层架构:有效降低层与层之间的依赖 | 16:45 |
| 08 | 微服务架构模型:几种常见模型的对比和分析 | 16:34 |
| 09 | 中台:数字转型后到底应该共享什么?| 18:23 |
| 10 | DDD、中台和微服务:它们是如何协作的?| 14:32 |
| - | 答疑:有关3个典型问题的讲解 | 11:03 |
### 实战篇
| 序号 | 标题 | |
| --- | -------------------------- | ----------------------------- |
| 11 | DDD实践:如何用DDD重构中台业务模型?| |
| 12 | 领域建模:如何用事件风暴构建领域模型?| 事件风暴说白了就是一起开个会,定义业务名词和对应的代码命名 |
| 13 | 代码模型(上):如何使用DDD设计微服务代码模型?| |
| 14 | 代码模型(下):如何保证领域模型与代码模型的一致性?| |
| 15 | 边界:微服务的各种边界在架构演进中的作用?| |
| 16 | 视图:如何实现服务和数据在微服务各层的协作?| |
| 17 | 从后端到前端:微服务后,前端如何设计?| |
| 18 | 知识点串讲:基于DDD的微服务设计实例 | |
| 19 | 总结(一):微服务设计和拆分要坚持哪些原则?| |
| 20 | 总结(二):分布式架构关键设计10问 | |
### 结束语
| 序号 | 标题 | 时长 |
|------|------|------|
| 1 | 结束语 \| 所谓高手,就是跨过坑和大海!| 08:18 |
### 专栏加餐
| 序号 | 标题 | 时长 |
|------|------|------|
| 1 | 基于DDD的微服务设计实例代码详解 | 26:01 |
| 2 | 抽奖|《DDD实战课》沉淀成书了,感谢有你!| 09:26 |
### 期末测试
| 序号 | 标题 | 时长 |
|------|------|------|
| 1 | 期末测试 \| 有关DDD的内容,你掌握了多少呢?| 00:30 |