共计 1804 个字符,预计需要花费 5 分钟才能阅读完成。
糟糕分层设计的代价
先看两个真实案例:

-
修改扩散问题:某金融系统每次新增字段都需要修改 5 个不同层级的文件,因为业务逻辑直接混在 DAO 层里。一个简单的需求变更导致上百行代码改动,上线后出现数据不一致
-
测试困境:某电商促销模块因为控制层直接调用数据库连接,写单元测试需要启动整个 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 等持久化框架}
}
依赖倒置实现
- 领域层定义
OrderRepository接口 - 基础设施层实现该接口
- 应用层通过构造函数注入接口(Spring 会自动找到实现类)
性能优化策略
- DTO 复用:对性能敏感的场景,可以考虑在内部层间复用 DTO
- 批量操作:避免在循环中进行跨层调用
- 懒加载:对关联数据采用按需加载模式
新手三大陷阱
- 过度分层(比如把简单查询拆到 7 个层)
-
解法:遵循 YAGNI 原则,初期可以用三层架构
-
循环依赖(A 层依赖 B 层,B 层又反向依赖 A 层)
-
解法:引入中间层或依赖倒置
-
贫血模型(把业务逻辑全塞到 Service 层)
- 解法:采用领域驱动设计,将业务逻辑放到实体中
自查清单
- [] 每层是否有明确单一职责
- [] 上层是否只依赖下层接口而非具体实现
- [] 是否避免了跨层调用(如 Controller 直接访问 DAO)
- [] 领域对象是否包含业务行为而不仅是 getter/setter
延伸学习
- 书籍:《实现领域驱动设计》
- 工具:ArchUnit(用于架构约束测试)
- 开源项目:Spring PetClinic(经典分层示例)
实际开发中,分层没有绝对标准答案。建议先掌握基础模式,再根据业务复杂度逐步调整。关键是要保持层间界限清晰,这样系统才能随着业务增长保持可维护性。
正文完
