DDD的分层架构是怎么样的?

30 阅读4分钟

领域驱动设计(DDD)的分层架构旨在通过关注点分离职责明确来组织代码,使领域模型成为系统的核心,并隔离技术复杂性。以下是典型的分层架构及其职责,结合Java代码示例说明:


DDD分层架构(经典四层)

1. 用户接口层(User Interface Layer / Presentation Layer)

  • 职责
    • 处理用户输入(HTTP请求、命令行、消息队列等)。
    • 返回响应(JSON、HTML等)。
    • 不包含业务逻辑,仅负责输入/输出转换。
  • Java实现
    // 示例:Spring MVC的Controller
    @RestController
    @RequestMapping("/orders")
    public class OrderController {
        @Autowired
        private OrderApplicationService orderAppService;
    
        @PostMapping
        public ResponseEntity<Void> createOrder(@RequestBody CreateOrderRequest request) {
            // 1. 转换DTO为领域对象
            CreateOrderCommand command = new CreateOrderCommand(request.getItems());
            // 2. 调用应用服务
            orderAppService.createOrder(command);
            return ResponseEntity.ok().build();
        }
    }
    

2. 应用层(Application Layer)

  • 职责
    • 协调领域对象完成用例(如事务管理、权限校验)。
    • 不包含核心业务逻辑,仅定义用例流程。
    • 调用领域层的聚合根和领域服务。
  • Java实现
    @Service
    public class OrderApplicationService {
        @Autowired
        private OrderRepository orderRepository;
        @Autowired
        private EventPublisher eventPublisher;
    
        @Transactional
        public void createOrder(CreateOrderCommand command) {
            // 1. 创建聚合根
            Order order = new Order(UUID.randomUUID().toString());
            // 2. 调用领域对象方法
            command.getItems().forEach(order::addItem);
            // 3. 持久化
            orderRepository.save(order);
            // 4. 发布领域事件(跨聚合操作)
            eventPublisher.publish(new OrderCreatedEvent(order.getId()));
        }
    }
    

3. 领域层(Domain Layer)

  • 职责
    • 系统的核心,包含领域模型(实体、值对象、聚合根、领域服务)。
    • 封装业务规则和不变条件。
    • 不依赖任何其他层(完全独立于技术和框架)。
  • Java实现
    // 聚合根
    public class Order {
        private String orderId;
        private List<OrderItem> items;
        private OrderStatus status;
    
        public void addItem(OrderItem item) {
            if (status != OrderStatus.DRAFT) {
                throw new IllegalStateException("Cannot modify a confirmed order");
            }
            items.add(item);
        }
    
        public void confirm() {
            if (items.isEmpty()) throw new IllegalStateException("Empty order");
            this.status = OrderStatus.CONFIRMED;
        }
    }
    
    // 领域服务(处理跨聚合逻辑)
    public class OrderValidationService {
        public void validateOrder(Order order) {
            // 复杂的业务规则校验
        }
    }
    

4. 基础设施层(Infrastructure Layer)

  • 职责
    • 实现技术细节:数据库访问、消息队列、缓存、外部API调用等。
    • 实现领域层的接口(如仓储接口)。
  • Java实现
    // 实现领域层的仓储接口(JPA)
    @Repository
    public class JpaOrderRepository implements OrderRepository {
        @Autowired
        private OrderJpaRepository jpaRepository; // Spring Data JPA接口
    
        @Override
        public Order findById(String orderId) {
            OrderJpaEntity entity = jpaRepository.findById(orderId).orElseThrow();
            return convertToDomain(entity);
        }
    
        // 省略转换逻辑
    }
    
    // 消息队列实现(如Kafka)
    @Component
    public class KafkaEventPublisher implements EventPublisher {
        @Override
        public void publish(DomainEvent event) {
            kafkaTemplate.send("order-events", event);
        }
    }
    

分层依赖关系

  • 单向依赖
    用户接口层 → 应用层 → 领域层
    基础设施层 → 领域层
    (通过依赖倒置原则,领域层定义接口,基础设施层实现接口)

  • 关键原则

    • 领域层完全独立:不依赖Spring、JPA等技术框架。
    • 避免基础设施层侵入领域模型:领域对象不包含JPA注解或框架依赖。

代码结构示例(Maven/Gradle项目)

src/main/java
├── com.example
│   ├── application            // 应用层
│   │   ├── OrderApplicationService.java
│   │   └── dto               // DTO定义
│   ├── domain                // 领域层
│   │   ├── model             // 聚合根、实体、值对象
│   │   ├── service           // 领域服务
│   │   ├── event             // 领域事件
│   │   └── repository        // 仓储接口(领域层定义)
│   ├── infrastructure        // 基础设施层
│   │   ├── persistence       // 数据库实现(JPA)
│   │   ├── messaging         // 消息队列实现(Kafka)
│   │   └── rest              // 外部API调用
│   └── interfaces            // 用户接口层
│       ├── web               // HTTP接口(Controller)
│       └── cli               // 命令行接口

各层交互流程(以创建订单为例)

  1. 用户接口层接收HTTP请求,将JSON转换为CreateOrderCommand
  2. 应用层调用OrderApplicationService
    • 创建Order聚合根。
    • 调用order.addItem()添加商品项。
    • 调用仓储保存订单。
    • 发布OrderCreatedEvent
  3. 领域层执行核心业务逻辑:
    • Order聚合根校验状态和商品数量。
  4. 基础设施层
    • JpaOrderRepositoryOrder持久化到数据库。
    • KafkaEventPublisher将事件发送到消息队列。

分层架构的优势

  1. 高内聚低耦合:领域层与技术实现解耦。
  2. 可测试性:领域层可脱离框架单独测试。
  3. 适应变化:技术栈替换(如数据库从MySQL切到MongoDB)只需修改基础设施层。
  4. 清晰的职责划分:避免代码混杂(如业务逻辑侵入Controller)。

常见误区与解决方案

误区解决方案
业务逻辑泄露到应用层或Controller将逻辑内聚到领域对象(充血模型)。
领域层依赖Spring/JPA通过依赖倒置,领域层仅定义接口。
基础设施层直接依赖领域层具体类通过接口隔离,基础设施层实现领域层接口。

总结

DDD的分层架构通过领域层为核心,隔离技术与业务逻辑,确保软件的可维护性和扩展性。作为Java工程师,应重点关注:

  1. 领域层的纯粹性:避免技术框架污染领域模型。
  2. 依赖方向控制:通过接口和依赖倒置解耦各层。
  3. 代码结构清晰:模块化组织限界上下文(如每个上下文独立为子模块)。