切层技能入门指南:从零构建高效分层架构

2次阅读
没有评论

共计 1804 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

糟糕分层设计的代价

先看两个真实案例:

切层技能入门指南:从零构建高效分层架构

  1. 修改扩散问题:某金融系统每次新增字段都需要修改 5 个不同层级的文件,因为业务逻辑直接混在 DAO 层里。一个简单的需求变更导致上百行代码改动,上线后出现数据不一致

  2. 测试困境:某电商促销模块因为控制层直接调用数据库连接,写单元测试需要启动整个 Spring 容器,单测执行时间从秒级恶化到分钟级

主流分层模式对比

  • 经典三层架构(表现层 - 业务层 - 数据层)
  • 适合:传统 CRUD 应用,团队技术栈统一
  • 示例:Spring MVC + MyBatis 组合

  • 六边形架构(端口与适配器)

  • 适合:需要频繁对接外部系统的场景(如支付网关对接)
  • 特点:业务核心与外部实现完全解耦

  • CQRS 模式(命令查询职责分离)

  • 适合:读写负载差异大的系统(如数据分析平台)
  • 注意:会显著增加架构复杂度

电商订单模块分层实战

架构图示(PlantUML)

@startuml
package "表现层" {[OrderController]
}

package "应用层" {[OrderAppService]
}

package "领域层" {[Order]
  [OrderRepository]
}

package "基础设施层" {[OrderMapper]
  [MySQL]
}

[OrderController] -> [OrderAppService]
[OrderAppService] -> [OrderRepository]
[OrderRepository] --> [OrderMapper]
[OrderMapper] --> [MySQL]
@enduml

关键代码示例(Java)

DTO 定义(注意与实体分离)

// 表现层 DTO
public class OrderCreateDTO {
    @NotBlank
    private String productId;
    private Integer quantity;
    // 省略 getter/setter
}

// 领域实体
public class Order {
    private OrderId id;
    private List<OrderItem> items;
    // 包含业务方法
    public void validate() { /* 校验逻辑 */}
}

层间调用示例(依赖接口而非实现)

// 应用服务(依赖领域层接口)@Service
@RequiredArgsConstructor
public class OrderAppService {
    private final OrderRepository orderRepository;

    @Transactional
    public OrderResult createOrder(OrderCommand command) {Order order = new Order(command);
        order.validate(); // 业务规则校验
        return orderRepository.save(order);
    }
}

// 基础设施实现(实现领域层定义的仓储接口)@Repository
public class OrderRepositoryImpl implements OrderRepository {
    @Override
    public Order save(Order order) {// 调用 MyBatis 等持久化框架}
}

依赖倒置实现

  1. 领域层定义 OrderRepository 接口
  2. 基础设施层实现该接口
  3. 应用层通过构造函数注入接口(Spring 会自动找到实现类)

性能优化策略

  • DTO 复用:对性能敏感的场景,可以考虑在内部层间复用 DTO
  • 批量操作:避免在循环中进行跨层调用
  • 懒加载:对关联数据采用按需加载模式

新手三大陷阱

  1. 过度分层(比如把简单查询拆到 7 个层)
  2. 解法:遵循 YAGNI 原则,初期可以用三层架构

  3. 循环依赖(A 层依赖 B 层,B 层又反向依赖 A 层)

  4. 解法:引入中间层或依赖倒置

  5. 贫血模型(把业务逻辑全塞到 Service 层)

  6. 解法:采用领域驱动设计,将业务逻辑放到实体中

自查清单

  • [] 每层是否有明确单一职责
  • [] 上层是否只依赖下层接口而非具体实现
  • [] 是否避免了跨层调用(如 Controller 直接访问 DAO)
  • [] 领域对象是否包含业务行为而不仅是 getter/setter

延伸学习

  • 书籍:《实现领域驱动设计》
  • 工具:ArchUnit(用于架构约束测试)
  • 开源项目:Spring PetClinic(经典分层示例)

实际开发中,分层没有绝对标准答案。建议先掌握基础模式,再根据业务复杂度逐步调整。关键是要保持层间界限清晰,这样系统才能随着业务增长保持可维护性。

正文完
 0
评论(没有评论)