领域驱动设计(DDD)完全指南

一、什么是领域驱动设计?

领域驱动设计(Domain-Driven Design,简称DDD) 是一种软件开发方法论,由Eric Evans在2003年提出的《Domain-Driven Design: Tackling Complexity in the Heart of Software》一书中系统阐述。

DDD的核心思想是:将软件系统的核心业务逻辑放在领域模型中,让技术与业务紧密协作,共同演化

传统开发模式的问题

  • 业务逻辑散落在Service层、DAO层、甚至Controller层
  • 数据库表结构主导设计(数据库驱动开发)
  • 业务需求变化时,代码修改困难
  • 技术与业务沟通存在鸿沟

DDD的优势

  • 以业务领域为核心,建立通用语言
  • 代码结构清晰,易于维护和扩展
  • 更好地应对复杂业务场景
  • 提升团队协作效率

二、DDD核心概念

1. 领域(Domain)

领域是指软件系统所处理的业务范围和问题域。DDD将业务领域划分为多个子域(Subdomain),包括:

  • 核心域(Core Domain):业务核心竞争力,最重要的部分
  • 支撑域(Supporting Subdomain):为核心域提供支持
  • 通用域(Generic Subdomain):通用功能,可直接购买或外包

2. 实体(Entity)

实体是具有唯一标识的对象,其身份在生命周期内保持不变。

public class Order {
    private String orderId;  // 唯一标识
    private BigDecimal amount;
    private List<OrderItem> items;
    
    // 实体有身份,有自己的生命周期
}

3. 值对象(Value Object)

值对象是没有唯一标识的对象,不可变,通常用来描述实体的属性。

// 值对象示例
public class Money {
    private final BigDecimal amount;
    private final String currency;
    
    public Money(BigDecimal amount, String currency) {
        this.amount = amount;
        this.currency = currency;
    }
    
    // 值对象通常不可变,没有setter
}

4. 聚合根(Aggregate Root)

聚合根是聚合的根节点,负责维护聚合内部的一致性。外部对象只能通过聚合根来访问聚合内部的实体和值对象

5. 领域服务(Domain Service)

当某个业务逻辑不属于实体或值对象时,使用领域服务来承载。

public class OrderDomainService {
    
    public void placeOrder(Order order, InventoryService inventoryService) {
        // 跨多个实体的业务逻辑
        if (!inventoryService.checkStock(order.getItems())) {
            throw new InsufficientStockException();
        }
        order.place();
    }
}

6. 领域事件(Domain Event)

领域事件用于表达领域中发生的事情,实现事件驱动架构。

public class OrderPlacedEvent {
    private String orderId;
    private BigDecimal totalAmount;
    private LocalDateTime occurredOn;
    
    // 领域事件应该是不可变的
}

7. 仓储(Repository)

仓储是领域模型与数据存储之间的抽象,封装数据持久化逻辑。

public interface OrderRepository {
    Order findById(String orderId);
    void save(Order order);
    void delete(String orderId);
}

8. 工厂(Factory)

工厂负责复杂对象的创建,隐藏对象创建的复杂性。


三、DDD战略设计

1. 限界上下文(Bounded Context)

限界上下文是领域模型的边界,每个上下文有自己的通用语言和领域模型。

如何划分限界上下文?

  • 业务职责边界
  • 团队组织结构
  • 不同的数据库 schema
  • 明显的业务差异

2. 通用语言(Ubiquitous Language)

通用语言是团队成员在沟通中使用的统一语言,贯穿需求分析、设计、编码全过程。

3. 上下文映射(Context Mapping)

上下文映射描述不同限界上下文之间的关系:

  • 合作关系(Partnership):两个上下文紧密合作
  • 客户-供应商(Customer-Supplier):一方提供,一方消费
  • 共享内核(Shared Kernel):共享部分领域模型
  • 防腐层(Anti-Corruption Layer):隔离外部系统的影响
  • 开放主机服务(Open Host Service):提供服务接口
  • 遵奉者(Conformist):盲目跟随上游模型

四、DDD分层架构

经典四层架构

┌─────────────────────────────────────┐
│           Presentation              │  ← 用户界面层
├─────────────────────────────────────┤
│           Application               │  ← 应用层(用例)
├─────────────────────────────────────┤
│             Domain                  │  ← 领域层(核心业务)
├─────────────────────────────────────┤
│         Infrastructure              │  ← 基础设施层
└─────────────────────────────────────┘

各层职责

| 层级 | 职责 | |------|------| | 用户界面层 | 处理用户请求,返回响应 | | 应用层 | 编排领域逻辑,协调用例 | | 领域层 | 承载核心业务逻辑,领域模型 | | 基础设施层 | 数据库、缓存、第三方服务 |

依赖规则

  • 外层依赖内层:每一层只能依赖相邻的内层
  • 领域层是核心:不依赖任何其他层
  • 依赖注入:通过依赖倒置实现

五、DDD战术建模工具

1. 实体 vs 值对象

| 特性 | 实体 | 值对象 | |------|------|--------| | 标识 | 有唯一标识 | 无标识 | | 可变性 | 可变 | 不可变 | | 相等性 | 基于ID | 基于属性 | | 生命周期 | 有 | 无 |

2. 领域建模原则

  • 充血模型:业务逻辑放在领域对象中
  • 单一职责:每个类职责明确
  • 高内聚低耦合:相关逻辑放一起
  • 关注不变性:先考虑什么是不变的

3. 聚合设计原则

  • 聚合根负责维护一致性
  • 聚合内对象只能通过根访问
  • 跨聚合使用ID引用
  • 小聚合原则:减少事务边界

六、DDD实践步骤

1. 领域分析

  • 与业务专家深入沟通
  • 理解业务流程和规则
  • 识别核心领域和子域

2. 限界上下文划分

  • 确定系统边界
  • 定义各上下文职责
  • 建立上下文映射关系

3. 领域建模

  • 识别实体和值对象
  • 确定聚合根
  • 定义领域服务
  • 设计领域事件

4. 架构落地

  • 构建分层架构
  • 实现仓储接口
  • 编写应用服务
  • 对接基础设施

七、DDD实践建议

什么时候使用DDD?

✅ 复杂业务领域 ✅ 业务需求频繁变化 ✅ 团队超过一定规模 ✅ 需要长期维护的项目

❌ 简单CRUD系统 ❌ 业务逻辑简单的项目 ❌ 短期一次性项目

常见误区

  1. 不要过度设计:DDD适用于复杂场景,简单系统无需强求
  2. 不要贫血模型:避免把所有业务逻辑放在Service层
  3. 不要忽视通用语言:技术术语与业务术语要统一
  4. 不要照搬模式:根据实际情况灵活运用

推荐的DDD框架

  • Java: Spring Boot + DDD框架(如Axon、Colus)
  • Go:kratos、ent
  • .NET:ABP框架

八、总结

领域驱动设计是一套完整的软件开发方法论,它强调:

  1. 以业务为中心:用通用语言描述业务
  2. 模型驱动设计:领域模型是核心
  3. 持续迭代:与业务共同演化

DDD不是银弹,它适用于复杂的业务场景。在实践中,需要团队共同努力,不断探索和改进。


参考资料:

  • 《领域驱动设计:软件核心复杂性应对之道》- Eric Evans
  • 《实现领域驱动设计》- Vaughn Vernon

关注我,了解更多技术干货!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐