本文重点
但很多初学者接触 DDD 时,第一反应是:"概念太多了!领域、子域、限界上下文、聚合、实体、值对象……它们到底是什么关系?"这一讲的目标很直接:用一张图把所有核心概念串起来,让你先看到全貌,再逐个击破。所以我们先来了解一下。
一、一句话认识每个概念
先给每个概念一句极简的定义。你不需要现在就完全理解,只需要有一个初步印象。
战略设计(业务视角)
战略设计回答"业务边界在哪里"——从业务出发,划分领域、子域、限界上下文,建立领域模型,确定微服务边界。战略设计的概念如下:
概念 | 一句话定义 | 电商例子 |
|---|---|---|
领域 | 你要解决的整个业务问题 | 电商业务 |
子域 | 领域拆分后的小业务板块 | 订单、商品、用户、支付、库存、物流 |
核心域 | 公司最核心的竞争力,必须自己做 | 订单(交易的核心) |
通用域 | 通用能力,可以买现成的 | 支付(对接支付宝/微信) |
支撑域 | 必需但不是核心,可以简做 | 物流跟踪 |
限界上下文 | 语义边界,内部术语唯一 | 订单上下文、商品上下文 |
通用语言 | 团队内部统一使用的业务术语 | "订单"在订单上下文中就是"交易订单" |
战术设计(代码视角)
战术设计回答"模型怎么写成代码"——将战略设计产出的领域模型逐项落地为可运行的 Java 代码。战术设计中的常用概念如下:
概念 | 一句话定义 | 代码中的体现 |
|---|---|---|
聚合 | 一组必须一起保持一致的对象的集合 | Order.java+ |
聚合根 | 聚合的唯一入口,业务规则的守护者 | Order.java(含 |
实体 | 有唯一标识、状态可变的对象 | Order、 |
值对象 | 无标识、不可变、整体替换的对象 | OrderId、 |
领域服务 | 不属于单个实体的业务逻辑 | DiscountCalculationService.java |
应用服务 | 编排、协调、事务管理 | OrderApplicationService.java |
仓储接口 | 聚合的持久化接口定义(领域层) | OrderRepository.java |
仓储实现 | 仓储接口的实现(基础层) | OrderRepositoryImpl.java |
领域事件 | 已经发生的重要业务事实 | OrderPaidEvent.java |
二、事件风暴是什么
在DDD的实践中,事件风暴本身就是战略设计的核心方法,而不是一个可选的前置步骤。事件风暴是一种工作坊形式的头脑风暴方法。项目团队——包括领域专家、开发、产品、测试——坐在一起,用便利贴把业务流程逐步梳理出来,最终形成领域模型。
团队通过事件风暴探索业务边界、提取领域概念、划定限界上下文。
它的产出直接输入给战术设计。
事件风暴产出的领域模型——聚合、实体、值对象、领域事件等——直接作为战术设计的输入,指导代码实现。战术设计不需要再做一遍事件风暴。
层次 | 事件风暴的角色 |
|---|---|
战略层 | 核心方法:团队用事件风暴探索业务、划定边界、产出领域模型 |
战术层 | 输入来源:战略设计产出的领域模型直接作为战术设计的输入 |
用建桥来类比:
事件风暴是"建桥的过程"——动态的、协作的,需要团队围在一起讨论、贴便利贴、争论、收敛。领域模型是"桥本身"——静态的、结构化的,可以被反复查阅和使用。
桥的质量取决于建桥的过程。如果事件风暴做得潦草——参与人不全、讨论不充分、概念没有对齐——那么产出的领域模型就是一座不稳固的桥。
三、战略与战术的传递关系
你可能会有一个疑问:战略设计产出了这么多概念,战术设计又要实现这些概念——那中间靠什么连接?
答案是领域模型┌─────────────────────────────────────────────────────────────┐│ 战略设计 ││ 做什么:分析业务、划定边界、建立模型 ││ 方法:事件风暴 ││ 产出:领域模型 │└─────────────────────────────────────────────────────────────┘││ 发现(产出)▼┌─────────────────────────────────────────────────────────────┐│ 领域模型 ││ 是什么:业务概念及其规则的结构化表达 ││ 包含:聚合、实体、值对象、领域服务、领域事件、仓储接口 │└─────────────────────────────────────────────────────────────┘││ 输入▼┌─────────────────────────────────────────────────────────────┐│ 战术设计 ││ 做什么:将领域模型落地为可运行的代码 ││ 产出:Java类 │└─────────────────────────────────────────────────────────────┘
一句话总结:战略设计把领域模型"画"在图纸上,战术设计把领域模型"写"在代码里。
四、这些概念如何落地为代码
宏观:从领域到代码的完整路径
从领域出发,逐级拆分为子域,再划定限界上下文。限界上下文决定了微服务的边界。在限界上下文内部,建立领域模型,包含聚合、实体、值对象、领域服务、领域事件、仓储接口等。领域模型中的每一个概念,最终都会映射为微服务领域层中的 Java 类。
微观:概念到代码的具体映射
概念 | 代码中的体现 | 所在包 |
|---|---|---|
聚合根 | Order.java | domain/order/ |
实体 | OrderItem.java | domain/order/ |
值对象 | OrderId.java、 | domain/order/ |
领域服务 | DiscountCalculationService.java | domain/order/service/ |
仓储接口 | OrderRepository.java | domain/order/repository/ |
仓储实现 | OrderRepositoryImpl.java | infrastructure/repository/ |
领域事件 | OrderPaidEvent.java | domain/order/event/ |
应用服务 | OrderApplicationService.java | application/service/ |
控制器 | OrderController.java | interfaces/controller/ |
你不需要现在就记住这些,只需要知道:每一个 DDD 概念,最终都会在代码中有一个对应的位置,所以我们后面的学习逻辑就是先概念,后实现,只要跟着这个节奏就好了。
五、为什么需要这么多概念
你可能会想:"一个订单系统而已,需要这么多概念吗?"
答案是:简单的系统不需要,复杂的系统非常需要。
这些概念本质上是在解决不同层面的问题:
层面 | 解决的问题 | 对应的概念 |
|---|---|---|
业务边界 | 这个系统要做什么?不做什么? | 领域、子域 |
战略投入 | 哪些必须自己做?哪些可以买? | 核心域、通用域、支撑域 |
语义一致 | 团队沟通时不会产生歧义 | 限界上下文、通用语言 |
数据一致性 | 修改订单时,订单行不能出错 | 聚合、聚合根 |
业务内聚 | 业务逻辑不要散落各处 | 实体、领域服务 |
技术解耦 | 换数据库不要影响业务代码 | 仓储模式 |
服务解耦 | 微服务之间不要直接依赖 | 领域事件 |
每一个概念都是为了解决一个具体的问题而存在的。当你理解了"它解决了什么问题",这个概念就不再是抽象的名词,而是你工具箱里的一件工具。
总结
本文的内容呢,你只需要先了解,你不需要背,也不需要记,因为当你看完这个专栏的时候,你再回过头来,就会深刻的理解这些概念了。