一、核心理念:解决软件复杂性
DDD是一种应对复杂业务系统 的软件设计方法学,由Eric Evans在2004年提出。它的核心是将业务领域置于设计的中心,而非技术实现。
核心价值
-
对齐业务与技术语言,减少沟通成本
-
建立可演化的领域模型,适应业务变化
-
划分清晰的业务边界,降低系统耦合度
-
提高代码可读性和可维护性
二、战略设计:宏观架构规划
1. 统一语言(Ubiquitous Language)
业务人员和技术团队使用相同的术语和概念
示例:电商系统中的"订单(Order)"、"库存(SKU)"、"配送履约(Fulfillment)"
2. 限界上下文(Bounded Context)
定义:明确领域模型的边界,每个上下文内有一套独立完整的业务概念。

关键点:
-
不同上下文可以有不同的"客户"定义
-
通过上下文映射定义交互关系
-
避免一个大而全的"上帝模型"
3. 上下文映射模式
-
共享内核:多个团队共享部分模型
-
客户-供应商:上游服务于下游
-
防腐层:隔离外部系统的侵入性模型
-
开放主机服务:通过API暴露领域能力
-
遵奉者:完全采用上游模型
三、战术设计:微观实现模式
1. 实体(Entity)
-
具有唯一标识的对象
-
状态随时间变化,但ID不变
-
通过属性而非ID判断相等性
java
// 示例:订单实体
public class Order extends Entity<OrderId> {
private OrderStatus status;
private Money totalAmount;
private List<OrderLine> lines;
public void addItem(Product product, int quantity) {
// 业务规则:已支付的订单不能修改
if (status.isPaid()) {
throw new OrderAlreadyPaidException(id);
}
// 业务逻辑...
}
}
2. 值对象(Value Object)
-
没有唯一标识,通过属性定义
-
不可变(Immutable)
-
可替换性
java
// 示例:地址值对象
public record Address(
String street,
String city,
String postalCode
) {
// 值对象的相等性基于所有属性
@Override
public boolean equals(Object o) {
// 基于street、city、postalCode比较
}
}
3. 聚合(Aggregate)
核心概念:将相关对象组成一个一致性边界
-
一个聚合一个聚合根(唯一外部访问点)
-
聚合内强一致性,聚合间最终一致性
-
聚合根负责维护业务规则
java
// 示例:订单聚合
public class Order extends AggregateRoot<OrderId> {
private List<OrderLine> lines; // 聚合内实体
private Address shippingAddress; // 值对象
// 工厂方法
public static Order create(Customer customer, List<OrderItem> items) {
Order order = new Order();
// 初始化逻辑
order.addDomainEvent(new OrderCreatedEvent(order.id()));
return order;
}
// 业务方法
public void cancel() {
// 检查业务规则
if (!canBeCanceled()) {
throw new IllegalStateException("订单不能取消");
}
this.status = OrderStatus.CANCELLED;
addDomainEvent(new OrderCancelledEvent(this.id));
}
}
4. 领域服务(Domain Service)
-
处理不适合放在实体/值对象中的业务逻辑
-
无状态的操作
-
协调多个领域对象
java
public class OrderTransferService {
public void transferOrder(
Order fromOrder,
Order toOrder,
OrderLine line
) {
// 复杂的业务规则验证
validateTransfer(fromOrder, toOrder);
// 执行领域操作
fromOrder.removeLine(line);
toOrder.addLine(line);
// 发布领域事件
publishEvent(new OrderTransferredEvent(...));
}
}
5. 领域事件(Domain Event)
-
表示领域中已发生的重要事情
-
用于解耦和事件驱动架构
java
public class OrderPaidEvent implements DomainEvent {
private OrderId orderId;
private Money amount;
private LocalDateTime paidAt;
// 事件应包含足够的信息供其他边界消费
}
6. 仓储(Repository)
-
封装聚合的持久化逻辑
-
面向聚合根提供类似集合的接口
java
public interface OrderRepository {
// 只通过聚合根ID查找
Optional<Order> findById(OrderId id);
// 保存聚合根(包括其内部所有对象)
void save(Order order);
// 基于业务规则的查询
List<Order> findPendingOrders(CustomerId customerId);
}
7. 工厂(Factory)
-
封装复杂对象的创建逻辑
-
保持聚合的完整性
java
public class OrderFactory {
public Order createOrder(
Customer customer,
List<Product> products,
ShippingPlan shipping
) {
// 复杂的创建逻辑
validateProductsAvailability(products);
calculateDeliveryTime(shipping);
return new Order(...);
}
}
四、分层架构
java
┌─────────────────────────────────────┐
│ 用户界面层 │
│ (Presentation/Interface Layer) │
├─────────────────────────────────────┤
│ 应用层 │
│ (Application Layer) │
│ - 用例协调 │
│ - 事务边界 │
│ - DTO转换 │
├─────────────────────────────────────┤
│ 领域层 │
│ (Domain Layer) │
│ - 实体/值对象/聚合 │
│ - 领域服务/领域事件 │
│ - 仓储接口 │
├─────────────────────────────────────┤
│ 基础设施层 │
│ (Infrastructure Layer) │
│ - 仓储实现 │
│ - 外部服务调用 │
│ - 消息队列/数据库 │
└─────────────────────────────────────┘
依赖方向:上层依赖下层,领域层不依赖任何其他层
五、DDD与微服务架构
映射关系
限界上下文 → 微服务边界
聚合 → 服务内的一致性边界
领域事件 → 服务间集成方式
实施模式
微服务A(订单服务):
限界上下文: 订单管理
聚合: 订单、订单项
对外发布: OrderCreatedEvent
微服务B(库存服务):
限界上下文: 库存管理
订阅事件: OrderCreatedEvent
执行: 库存预留操作
六、实施DDD的关键考量
何时使用DDD
-
✅ 适用场景
-
业务逻辑复杂,规则多变
-
长生命周期系统
-
需要与业务专家深度协作
-
团队规模较大,需要明确边界
-
-
❌ 不适用场景
-
简单CRUD应用
-
原型或短期项目
-
技术导向而非业务导向的系统
-
实施阶段
-
探索期(1-2个月)
-
事件风暴工作坊
-
识别核心子域、通用子域、支持子域
-
定义初步的限界上下文
-
-
设计期(2-3个月)
-
设计聚合和领域模型
-
定义上下文映射关系
-
制定团队协作规范
-
-
实现期(持续演进)
-
迭代实现核心域
-
建立领域层代码规范
-
持续重构,保持模型纯净
-
常见陷阱
-
过度设计:为简单业务引入复杂DDD
-
贫血模型:实体变成只有getter/setter的数据容器
-
限界上下文划分不当:边界模糊或过度拆分
-
忽略统一语言:技术团队和业务团队各说各话
-
基础设施污染领域层:领域对象依赖具体技术
七、现代DDD演进
清洁架构/六边形架构
-
更强调依赖方向:领域层在最内层
-
端口与适配器模式
-
框架无关的领域模型
CQRS(命令查询职责分离)
java
// 命令端:处理业务操作
@Command
public class PlaceOrderCommand {
private CustomerId customerId;
private List<OrderItem> items;
}
// 查询端:优化数据读取
public class OrderView {
// 专为展示优化的数据结构
private String orderNumber;
private List<OrderItemView> items;
}
事件溯源(Event Sourcing)
-
不存储当前状态,存储状态变化事件
-
通过重放事件重建状态
-
天然支持审计追溯
九、学习路径建议
-
入门阶段(1-2周)
-
阅读《领域驱动设计精粹》
-
理解实体/值对象/聚合核心概念
-
-
实践阶段(1-2个月)
-
在小项目中应用战术模式
-
练习事件风暴工作坊
-
-
进阶阶段(3-6个月)
-
阅读《实现领域驱动设计》
-
在复杂系统中划分限界上下文
-
结合微服务架构实践
-
-
精通阶段(持续)
-
阅读《领域驱动设计》原著
-
参与复杂业务系统架构设计
-
指导团队建立DDD文化和规范
-
十、总结
DDD不是一套可以机械套用的框架,而是思维方式和工作方法。其核心价值在于:
-
建立深度业务理解:通过与业务专家协作,建立准确反映业务本质的模型
-
创建可持续的软件:随着业务演化,软件能够以可控的方式持续演进
-
提升团队效率:清晰的边界和统一语言降低协作成本
记住 :DDD的终极目标不是"完美设计",而是通过模型驱动,构建能够有效解决业务问题的软件系统。保持模型的活力,让它与业务一同成长,这才是DDD的真正精神。