架构(01):分层架构——经典分层、整洁架构、六边形架构
更新时间:2026-09-02。本文是
architecture/架构领域第 01 篇,在 架构总纲下。分层架构是软件架构的起点,把关注点分离。从经典三层到整洁架构、六边形架构,核心思路都是"高层不依赖低层"。
本文要回答的问题
- 经典三层架构(表现层/业务层/数据层)怎么划分?
- 三层架构的痛点是什么?为什么容易变成"四层"?
- 整洁架构的依赖反转怎么做到的?和三层架构本质区别?
- 六边形架构的 Ports 和 Adapters 分别是什么?
一、经典三层架构
最常见的分层方式:
┌──────────────────────────────────┐
│ 表现层(Presentation Layer) │
│ Controller / View / DTO │
│ 负责:处理 HTTP 请求,返回响应 │
├──────────────────────────────────┤
│ 业务层(Business Layer) │
│ Service / Domain / Business │
│ 负责:核心业务逻辑 │
├──────────────────────────────────┤
│ 数据层(Data Layer) │
│ Repository / DAO / Entity │
│ 负责:数据库读写 │
└──────────────────────────────────┘分层原则:
- 上层依赖下层,下层不依赖上层
- 表现层依赖业务层,业务层依赖数据层
- 每层只做自己的事,不越界
三层架构的痛点:
1. 业务层容易变"中转层"
表现层直接调数据层的方法
业务层变成空壳,代码散落到各层
2. 数据层泄露到业务层
业务逻辑里出现 SQL 语句
业务层直接操作数据库连接
3. 测试困难
要测业务层,必须先启动数据库
业务逻辑和基础设施耦合
4. 框架绑定
业务层继承框架的基类(如 Controller 继承框架类)
换框架时,业务层代码也要改二、整洁架构(Clean Architecture)
Robert C. Martin 提出,解决三层架构的痛点
┌───────────────────────────────────────────────┐
│ ┌───────────────────────────────────────┐ │
│ │ 企业业务规则(Entities) │ │
│ │ 核心业务实体,不依赖任何框架 │ │
│ └───────────────────────────────────────┘ │
│ ┌───────────────────────────────────────┐ │
│ │ 应用业务规则(Use Cases) │ │
│ │ 业务用例,编排实体和流程 │ │
│ └───────────────────────────────────────┘ │
│ ┌───────────────────────────────────────┐ │
│ │ 接口适配(Interface Adapters) │ │
│ │ Controller / Presenter / Gateway │ │
│ └───────────────────────────────────────┘ │
│ ┌───────────────────────────────────────┐ │
│ │ 基础设施(Frameworks & Drivers) │ │
│ │ DB / Web / UI / 外部服务 │ │
│ └───────────────────────────────────────┘ │
└───────────────────────────────────────────────┘依赖规则:
依赖必须从外向内,外层依赖内层,内层不依赖外层
内层(Entities):
不依赖任何框架、数据库、UI
纯业务逻辑,可以用普通对象实现
中层(Use Cases):
依赖 Entities,不依赖外部
定义输入输出接口(接口在内层,实现在外层)
外层(Adapters/Frameworks):
实现内层定义的接口
数据库、Web 框架、UI 都在外层与三层架构的本质区别:
三层架构:上层依赖下层(表现层 → 业务层 → 数据层)
整洁架构:外层依赖内层(基础设施 → 用例 → 实体)
核心变化:依赖反转(Dependency Inversion)
三层架构中,业务层直接依赖数据层
整洁架构中,业务层定义接口(Repository 接口),数据层实现接口
业务层不依赖数据层,两者都依赖抽象三、六边形架构(Ports & Adapters)
六边形架构,也叫端口与适配器架构
核心思想:应用是一个六边形,通过端口(Ports)与外部通信
┌──────────────────────────────────────────────────┐
│ 应用(六边形) │
│ │
│ ┌───────────┐ ┌───────────┐ │
│ │ Inbound │ │ Outbound │ │
│ │ Ports │ 业务逻辑 │ Ports │ │
│ │ (输入) │ ←───────│ (输出) │ │
│ └─────┬─────┘ └─────┬─────┘ │
│ │ │ │
│ ┌─────┴─────┐ ┌─────┴─────┐ │
│ │ Adapters │ │ Adapters │ │
│ │ Controller│ │ Repository│ │
│ │ CLI │ │ HTTP Client│ │
│ └───────────┘ └───────────┘ │
└──────────────────────────────────────────────────┘Ports(端口):
- 应用暴露给外部的接口(输入端口)
- 应用需要从外部获取的接口(输出端口)
- 端口定义在应用内部,不依赖外部
Adapters(适配器):
- 实现端口的代码
- 输入适配器:Controller、CLI、MQ Consumer
- 输出适配器:Repository、HTTP Client、MQ Producer
和整洁架构的关系:
- 六边形架构 = 整洁架构的另一种表述
- 端口 = 内层定义的接口
- 适配器 = 外层实现的接口
四、洋葱架构
与整洁架构、六边形架构类似,只是画成洋葱形状
外层 → 基础设施
中间 → 应用服务
内层 → 领域模型
依赖规则:从外到内,内层不依赖外层三种架构总结:
| 架构模式 | 核心思想 | 和整洁架构的关系 |
|---|---|---|
| 经典三层 | 上层依赖下层 | 容易被打破 |
| 整洁架构 | 外层依赖内层,依赖反转 | 最清晰 |
| 六边形架构 | 端口 + 适配器 | 等价于整洁架构 |
| 洋葱架构 | 分层依赖,从外到内 | 等价于整洁架构 |
五、实际项目怎么选
小项目(< 5 万行):
经典三层够用,不要过度设计
业务逻辑简单,用三层足够
中等项目(5-50 万行):
整洁架构,用依赖反转解耦
业务层定义接口,基础设施实现
代码清晰,测试方便
大项目(> 50 万行):
六边形架构 + 模块化拆分
每个模块独立六边形
模块间通过端口通信实际建议: 不要一开始就用整洁架构,容易过度设计。先做三层,等发现业务层和数据层耦合严重时,再引入依赖反转。
相关与延伸
下一篇:微服务拆分——限界上下文、数据一致性、服务间调用、演进策略;DDD 领域驱动设计,见 DDD 领域驱动设计。
一句话总结
分层架构:经典三层(表现层/业务层/数据层)上层依赖下层,容易耦合;整洁架构通过依赖反转使外层依赖内层,核心业务不依赖框架,可测试性好;六边形架构的端口(应用内部定义接口)和适配器(外部实现接口)等价于整洁架构;洋葱架构同理;小项目用三层,中等项目用整洁架构,大项目用六边形架构 + 模块化;不要一开始就过度设计,等耦合严重时再引入依赖反转。