7Implementing Domain-Driven Design

架构

架构实现

六边形架构CQRS事件溯源REST

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第7章:架构(Architecture)

一、导读

1.1 本章学习目标

第7章讲解 DDD 的架构实现——如何将领域模型映射到代码架构。

本章的核心学习目标包括:

  • 理解六边形架构(Hexagonal Architecture)
  • 掌握分层架构的 DDD 实现
  • 学会使用 REST 和 DDD 结合
  • 理解 DDD 与微服务的关系

1.2 为什么本章如此重要

好的架构能让领域模型成为系统的核心,而不是被技术细节淹没。六边形架构将领域逻辑与外部关注点(数据库、UI、消息队列)隔离开来,让领域模型保持纯净。

1.3 核心问题引导

六边形架构的核心思想是什么?

依赖倒置在 DDD 架构中如何体现?

DDD 和微服务有什么关系?

如何在实际项目中组织 DDD 的代码结构?


二、核心概念详解

2.1 六边形架构

六边形架构(端口和适配器):

         ┌──────────────┐
  REST ──│              │── Database
         │   领域核心    │
  MQ  ───│  (Entities,  │── Email
         │   Services)  │
  UI  ───│              │── External API
         └──────────────┘

端口(Port):领域核心定义的接口
适配器(Adapter):接口的具体实现

依赖方向:外部 → 内部(领域核心不依赖外部)

2.2 分层架构

DDD 分层架构:

1. 接口层(Interface Layer)
   - REST Controller
   - 消息监听器
   - 定时任务

2. 应用层(Application Layer)
   - 应用服务
   - 命令处理
   - 事件发布

3. 领域层(Domain Layer)
   - 实体、值对象
   - 领域服务
   - 领域事件
   - 仓储接口

4. 基础设施层(Infrastructure Layer)
   - 仓储实现
   - 外部服务适配器
   - 数据库配置

依赖方向:外层 → 内层

2.3 代码组织

src/main/java/com/example/order/
├── domain/                    # 领域层
│   ├── model/
│   │   ├── Order.java
│   │   ├── OrderLine.java
│   │   ├── OrderId.java
│   │   └── OrderStatus.java
│   ├── service/
│   │   └── OrderDomainService.java
│   ├── event/
│   │   ├── OrderPlaced.java
│   │   └── OrderConfirmed.java
│   └── repository/
│       └── OrderRepository.java    # 接口
│
├── application/               # 应用层
│   ├── OrderApplicationService.java
│   ├── command/
│   │   ├── PlaceOrderCommand.java
│   │   └── ConfirmOrderCommand.java
│   └── event/
│       └── OrderEventHandler.java
│
├── interfaces/                # 接口层
│   ├── rest/
│   │   └── OrderController.java
│   └── rest/dto/
│       └── OrderDTO.java
│
└── infrastructure/            # 基础设施层
    ├── persistence/
    │   ├── JpaOrderRepository.java
    │   └── OrderEntity.java
    └── messaging/
        └── KafkaOrderEventPublisher.java

2.4 DDD 与微服务

DDD 和微服务的关系:
- 限界上下文 ≈ 微服务
- 每个微服务有自己的领域模型
- 微服务之间通过 API 或事件通信
- 每个微服务可以独立部署和扩展

微服务中的 DDD:
- 每个服务内部使用 DDD
- 服务之间使用上下文映射
- 共享内核 → 共享库
- 客户-供应商 → REST API
- 发布/订阅 → 消息队列

三、实战案例

3.1 案例一:完整的 DDD 架构实现

java
// 领域层 - 实体
@Entity
@Table(name = "orders")
public class Order {
    @EmbeddedId
    private OrderId id;
    
    @Embedded
    private CustomerId customerId;
    
    @ElementCollection
    private List<OrderLine> lines;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    // 领域逻辑
    public void confirm() {
        if (status != OrderStatus.DRAFT) {
            throw new IllegalStateException();
        }
        if (lines.isEmpty()) {
            throw new IllegalStateException();
        }
        status = OrderStatus.CONFIRMED;
    }
}

// 应用层 - 服务
@Service
public class OrderApplicationService {
    private final OrderRepository orderRepo;
    private final EventPublisher eventPublisher;
    
    @Transactional
    public OrderId placeOrder(PlaceOrderCommand cmd) {
        Order order = new Order(cmd.getCustomerId());
        for (LineCommand line : cmd.getLines()) {
            order.addLine(line.getProductId(), line.getQuantity());
        }
        orderRepo.save(order);
        eventPublisher.publish(new OrderPlaced(order.getId()));
        return order.getId();
    }
}

// 接口层 - REST
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    private final OrderApplicationService orderService;
    
    @PostMapping
    public ResponseEntity<OrderResponse> placeOrder(@RequestBody PlaceOrderRequest req) {
        OrderId id = orderService.placeOrder(req.toCommand());
        return ResponseEntity.created(URI.create("/api/orders/" + id)).build();
    }
}

四、本章小结

六边形架构:领域核心 + 端口和适配器。

分层架构:接口层、应用层、领域层、基础设施层。

代码组织:按 DDD 概念组织包结构。

DDD + 微服务:限界上下文 ≈ 微服务。


五、思考与练习

为一个电商系统画出六边形架构图。

设计 DDD 分层架构的代码组织方案。

如何将一个单体 DDD 应用拆分为微服务?


7/7架构
0%