经典三层架构:表现层、业务逻辑层、数据访问层
说到软件分层,三层架构是绕不开的经典。我入行那会儿,第一个参与的企业项目就是基于这个模式。说实话,当时觉得不就是分三个文件夹嘛,后来被现实狠狠教育了一顿——分层的核心不是分文件夹,而是划清职责边界。
这一章,咱们就深入聊聊每一层到底该干什么、不该干什么,以及层与层之间怎么协作才不拧巴。
3.1 表现层(UI Layer)——只做“翻译”
表现层的职责很纯粹:把用户的操作转成请求,把后端的数据转成界面。它不应该知道业务规则,也不该直接操作数据库。
我在项目中见过最典型的反例:一个 Controller 里写了 200 行 SQL 拼接逻辑。嗯,那代码后来谁都不敢动。表现层一旦掺和业务,维护成本直接翻倍。
表现层该有的样子
- 接收输入:表单提交、点击事件、API 请求参数
- 调用业务层:把参数传给 Service,等结果回来
- 渲染输出:把 Service 返回的数据转成 JSON、HTML 或视图模型
- 简单校验:比如字段非空、格式检查(但别做业务校验)
3.2 业务逻辑层(Business Logic Layer)——核心战场
这一层是系统的灵魂。所有业务规则、计算、状态流转、权限判断,都应该在这里完成。我把它叫做“不可质疑的决策层”——表现层不能替它做决定,数据层不能替它做判断。
你想想看,如果业务逻辑散落在各个 Controller 或者 SQL 存储过程里,将来改需求的时候,你根本不知道要去哪里改。我曾经接手过一个项目,一个订单折扣规则分散在 7 个地方……那感觉,就像在迷宫里找出口。
业务逻辑层的职责清单
| 职责 | 说明 | 反例 |
|---|---|---|
| 业务规则 | 比如“VIP 用户满 100 减 20” | 在 SQL 里写 CASE WHEN |
| 状态流转 | 比如“订单已支付 → 已发货” | 在前端直接改状态字段 |
| 权限校验 | 比如“只有管理员能删除” | 在 DAO 层判断角色 |
| 事务管理 | 保证多个操作要么全成功要么全失败 | 在表现层开事务 |
3.3 数据访问层(Data Access Layer)——只做“搬运”
数据访问层,说白了就是跟数据库打交道的。它的任务很简单:CRUD。但简单不代表可以乱来。这一层的核心约束是——不包含任何业务逻辑。
我见过很多项目在 DAO 层里写 if-else 判断用户类型,然后决定查哪张表。这其实已经越界了。数据访问层应该像一台自动售货机:你投币(传参),它出货(返回数据),它不管你是谁、为什么买。
数据访问层的正确姿势
- 只做数据映射:把数据库表映射成对象,或者把对象写回数据库
- 提供查询接口:比如 findById、save、delete
- 不写业务判断:哪怕是一个简单的 if,也要往上提到业务层
- 不跨表做复杂关联:复杂查询应该在业务层组合,或者在数据库视图里处理
3.4 层间依赖关系——谁依赖谁?
三层架构的依赖方向是单向的、自上而下的:
表现层 → 业务逻辑层 → 数据访问层
每一层只依赖它的下一层,绝不反向依赖。更关键的是:每一层都通过接口依赖,而不是具体实现。这样你换数据库、换前端框架,都不会影响其他层。
我早期做项目时,业务层直接 new 了一个 DAO 实现类。后来要加缓存,得改业务层代码。改成接口注入后,加缓存只需要新增一个实现类,业务层完全不知情——这才是分层该有的样子。
3.5 一张图看懂三层架构
下面这张图展示了三层之间的调用关系和边界。注意看箭头方向和数据流动:
3.6 实战中的常见误区
理论说完了,聊聊我踩过的坑。这些误区几乎每个团队都会遇到:
| 误区 | 表现 | 后果 | 正确做法 |
|---|---|---|---|
| 层间泄漏 | 表现层直接调用 DAO | 业务逻辑分散,改一处崩一片 | 所有请求必须经过业务层 |
| 贫血业务层 | 业务层只是 DAO 的传话筒 | 业务规则散落在各处 | 业务层要有自己的判断和计算 |
| 胖表现层 | Controller 里写大量 if-else | 难以测试,难以复用 | 把逻辑下沉到业务层 |
| 数据层越界 | DAO 里做权限判断 | 换数据库时业务逻辑丢失 | 权限判断只放在业务层 |
3.7 接口定义在分层中的角色
三层架构能跑得顺,接口是关键。每一层之间的契约,就是接口。接口定义得好,层与层之间就像齿轮一样咬合紧密;定义得不好,改一个接口,上下游全得跟着改。
我个人习惯在业务层先定义接口,再写实现。这样数据访问层和表现层都可以并行开发——只要接口不变,大家各干各的。这也是《接口定义与软件分层协同设计实战》这门课的核心思想:先定契约,再写代码。
createOrder 比 insertOrderIntoDB 好得多——前者是业务语义,后者是实现细节。
好了,三层架构的核心内容就这些。记住一句话:每一层都有自己的战场,别越界。表现层管好界面,业务层管好规则,数据层管好存储。各司其职,系统才能健康。