分层与依赖方向是什么
分层架构的核心不是目录结构,而是依赖方向:外层可以依赖内层,内层不感知外层。Clean Architecture 把它画成同心圆——实体在中心,往外依次是用例、接口适配器、框架与驱动。依赖需要穿过边界反向指回内层时,由内层定义接口、外层提供实现,这就是依赖倒置在分层里的用法。
基本信息
| 方向 | 外向内依赖,内对外无感 |
|---|---|
| 边界 | 依赖倒置跨越:端口定义在内、实现在外 |
| 检验 | 核心模块的 import 里不出现框架与存储类型 |
| 相关模型 | 六边形架构、端口与适配器、整洁架构 |
落地要点
- 内层只依赖语言标准库与自己的抽象,不依赖 Web 框架或 ORM
- 持久化、消息、外部 API 的接口由内层定义,实现在外层
- 领域对象不应直接抛出框架专属异常,细节从内向外泄漏
- 跨层调用要有明确理由,临时直连应标注为待偿还项
- 用构建期检查固化依赖规则,让它不依赖人的自觉
- 数据模型分界要清晰:DTO 与领域对象分开,避免一层改字段层层改
分层示例
分层示例
entity ← usecase ← adapter ← framework
// 用例层定义端口(依赖倒置的关键)
interface UserRepo { Optional<User> findById(UserId id); }
// 基础设施层实现端口(外圈)
class JpaUserRepo implements UserRepo { /* JPA 细节在此 */ }
// 用例层只认接口
class RegisterUser {
private final UserRepo repo;
void handle(Cmd cmd) { repo.save(User.create(cmd)); }
}各层职责
| 层 | 职责 | 不该出现的东西 |
|---|---|---|
| 实体 | 业务不变量与规则 | 持久化注解、HTTP 类型 |
| 用例 | 编排流程、事务边界声明 | SQL、框架配置 |
| 适配器 | 协议转换、调用转发 | 业务规则 |
| 框架与驱动 | I/O、序列化、外部集成 | 领域决策 |
分层最常见的失败是只落在目录名上:包结构好看,但用例层直接 import 了持久化实现,规则形同虚设。可行的检验方式是在 CI 里跑依赖检查,让违规的代码合不进去。
分层数量不是目的:一个小型服务里实体层与用例层合并完全合理。判断依据是「这一层是否承担了独立的、可能独立变化的责任」,而不是别人家的架构图有几层。