2、分层架构总览:表现层、业务层、数据层、基础设施层的职责划分
聊到分层架构,我脑子里第一个蹦出来的画面,是十年前我刚带团队时做的一个「大泥球」项目。所有代码揉在一起,表现层里塞着SQL,业务逻辑里混着HTML标签。改一个按钮颜色,能引发数据库连接池崩溃。嗯,那滋味,谁尝谁知道。
后来我痛定思痛,开始认真搞分层。说白了,分层架构就是把一个复杂的系统,按照职责切分成几个独立的「房间」。每个房间只干自己的事,房间之间通过明确的「门」(接口)来沟通。这样做的好处,你想想看——改一个房间的装修,不会影响到隔壁的承重墙。
今天我们就来拆解这四个核心层:表现层、业务层、数据层、基础设施层。我会结合我在AP平台(自适应平台)项目中的实际经验,把每一层的职责、边界、以及最容易踩的坑,给你讲透。
2.1 表现层:用户的「脸面」
表现层,也叫UI层或展示层。它的职责只有一个:跟用户打交道。
用户看到的页面、填写的表单、点击的按钮、弹出的提示,全归它管。但请注意——它只管「展示」和「交互」,不管「业务逻辑」。
我在项目中遇到过一种典型错误:前端工程师为了省事,直接在JavaScript里写「如果用户余额大于100,显示VIP标识」。这看起来方便,但一旦业务规则变了(比如VIP门槛改成200),你就得改前端代码,还得重新发版。更可怕的是,如果多个前端(Web、App、小程序)都写了同样的逻辑,改起来就是一场噩梦。
正确的做法是什么?表现层只负责调用接口,拿到数据后原样展示。判断逻辑交给业务层。
// ❌ 错误:表现层处理业务逻辑
if (user.balance > 100) {
showVIPBadge();
}
// ✅ 正确:表现层只展示结果
// 调用业务层接口,拿到 isVIP 字段
if (response.isVIP) {
showVIPBadge();
}
2.2 业务层:系统的「大脑」
业务层是整个架构的核心。所有的业务规则、流程编排、状态流转,都在这里完成。
我个人习惯把业务层再细分成两块:
- 领域服务:处理核心业务逻辑,比如「计算订单金额」「校验用户权限」。
- 应用服务:负责流程编排,比如「下单流程」需要先校验库存、再扣减余额、最后生成订单。
为什么要分这么细?我曾经在一个项目中,把所有业务逻辑都写在一个叫 OrderService 的类里。结果这个类膨胀到8000行,改一个支付逻辑,要担心会不会影响退款逻辑。后来我把它拆成 OrderDomainService(领域)和 OrderApplicationService(应用),问题迎刃而解。
业务层还有一个容易被忽视的职责:事务管理。一个业务操作往往涉及多个数据变更,要么全部成功,要么全部回滚。这个「原子性」的保证,应该在业务层控制,而不是交给数据层。
2.3 数据层:信息的「仓库」
数据层负责数据的持久化、查询和缓存。它不关心数据怎么用,只关心数据怎么存、怎么取。
这里要特别注意:数据层不是「数据库层」。它包含但不限于:
| 组件 | 职责 | 举例 |
|---|---|---|
| Repository | 数据存取接口 | UserRepository.findById() |
| ORM映射 | 对象与数据库表的转换 | JPA Entity、MyBatis Mapper |
| 缓存层 | 提升读取性能 | Redis、本地缓存 |
| 数据源 | 连接管理 | MySQL、MongoDB、Elasticsearch |
数据层有一个铁律:只提供CRUD,不包含业务逻辑。比如,你不能在SQL里写 WHERE age > 18 来表示「成年人」——这个「18」是业务规则,应该放在业务层。
我记得有一次,团队里一位同事在Repository里写了一个 findActiveUsers() 方法,里面直接过滤了状态为「已注销」的用户。后来业务变了,需要展示已注销用户的历史记录,结果不得不改数据层代码。如果当初只提供 findAll(),过滤逻辑交给业务层,就不会有这个问题。
2.4 基础设施层:系统的「地基」
基础设施层是最容易被忽视的一层。它不直接处理业务,但所有层都依赖它。说白了,它就是「让系统能跑起来」的那些东西。
包括但不限于:
- 通信机制:RPC框架、消息队列、HTTP客户端
- 配置管理:配置中心、环境变量
- 日志与监控:日志收集、链路追踪、指标采集
- 安全认证:鉴权、加密、防攻击
- 通用工具:日期处理、序列化、异常处理
你可能会问:「这些不都是框架和中间件干的事吗?为什么要单独划一层?」
原因很简单:解耦。如果你的业务代码里直接调用了某个消息队列的API,哪天你想把RabbitMQ换成Kafka,就得改所有调用点。但如果通过基础设施层封装一层接口,业务层只依赖接口,底层随便换。
2.5 层与层之间的「交通规则」
分层架构最核心的约束是:上层依赖下层,下层不依赖上层。
具体来说:
- 表现层 → 依赖 → 业务层
- 业务层 → 依赖 → 数据层
- 数据层 → 依赖 → 基础设施层
- 基础设施层 → 不依赖任何上层
但这里有一个常见的「越级调用」问题。比如表现层直接调用数据层,跳过业务层。为什么不能这样?因为一旦跳过业务层,业务规则就没人执行了。你想想看,如果用户可以直接从页面调用「删除订单」的数据接口,那「只有管理员才能删除」这个规则谁来校验?
2.6 分层架构的「代价」
说了这么多好处,我也得泼点冷水。分层架构不是银弹,它也有代价:
- 代码量增加:每层都要写接口、实现类、DTO转换,代码量至少翻倍。
- 性能损耗:每多一层,就多一次方法调用和对象拷贝。对于极高并发场景,需要权衡。
- 学习成本:新成员需要理解每一层的职责和边界,上手周期变长。
但我的经验是:对于中大型项目,分层架构带来的维护收益,远大于它的代价。对于几十行代码的小工具,你当然可以不用分层。但一旦项目超过10万行代码,没有分层,你就是在给自己挖坑。
下一章,我会带你手把手搭建一个AP平台的分层架构原型,从项目结构到代码实现,咱们一步步来。到时候你会发现,分层架构一旦用顺手了,写代码就像搭积木一样清晰。