从混乱到有序的架构演进
目录导读
- 为什么需要代码分层? – 理解分层架构的核心意义
- 主流分层模式解析 – 经典三层架构与DDD分层对比
- 各层职责与边界 – 每层该放什么、不该放什么
- 常见分层误区与反模式 – 那些让代码变烂的“坏习惯”
- 分层规范的落地实践 – 技术选型、命名、依赖方向
- 常见问答(Q&A) – 解决你最关心的分层困惑
为什么需要代码分层?
在一次技术交流中,有位同事问我:“我们团队一直在写‘面条代码’,业务逻辑、数据库查询、UI渲染全混在一个文件里,改一个功能要翻遍整个项目,怎么办?”
这正是没有分层带来的痛苦,代码分层规范的核心目标是:
- 关注点分离:每一层只关心自己该做的事
- 可维护性:修改业务逻辑不需要去翻数据库代码
- 可测试性:可以单独测试服务层、数据访问层
- 团队协作:不同开发者可以并行工作在各自层上
分层不是“技术炫技”,而是让代码在复杂度增长时依然可控的生存法则。
主流分层模式解析
1 经典三层架构(表现层-业务层-数据层)
这是大多数中小型项目的首选:
- 表现层(Controller/API):接收请求、返回响应、参数校验
- 业务层(Service):核心业务逻辑、事务管理、规则编排
- 数据层(Repository/DAO):与数据库交互、ORM映射
2 DDD四层架构(领域驱动设计)
适合业务复杂、需要长期演进的项目:
- 接口层:对外API和DTO
- 应用层:编排领域服务、事务、权限
- 领域层:核心业务模型、领域服务、值对象
- 基础设施层:数据库、消息队列、第三方SDK封装
选择建议:如果业务逻辑主要是CRUD,三层架构就够;如果业务规则复杂(比如电商、金融),优先考虑DDD分层。
各层职责与边界
以下是一个典型的分层职责定义(以Java/Spring为例):
| 层 | 必须包含 | 严禁包含 |
|---|---|---|
| Controller | 参数校验、调用Service、返回DTO | 业务逻辑、数据库操作 |
| Service | 业务规则、调用Repository、事务 | HTTP请求、数据库查询SQL |
| Repository | 数据持久化、Mapper/ORM操作 | 业务逻辑、返回View对象 |
| DTO | 面向传输的数据结构 | 业务方法、数据库字段映射 |
关键原则:依赖方向必须从外向内,即Controller → Service → Repository,不能出现Repository直接调用Controller的情况。
常见分层误区与反模式
❌ 误区1:Service层太胖
表现:所有代码都塞在Service里,一个Service方法几百行,还在里面写SQL。
后果:无法复用,测试困难,修改一个功能可能影响其他功能。
❌ 误区2:Controller里写业务逻辑
表现:Controller直接操作数据库,或者进行复杂计算。
后果:业务逻辑暴露在API层,无法在Service层统一处理事务和校验。
❌ 误区3:跨层调用
表现:Repository直接返回View对象给Controller,或者Service返回Entity给前端。
后果:层与层之间耦合紧密,修改数据模型会波及多个层。
分层规范的落地实践
1 命名规范(以Java为例)
- Controller:
UserController、OrderController - Service:
UserService、OrderService - Repository:
UserRepository、OrderMapper - DTO:
UserRegisterRequest、UserVO - Entity/Model:
User、Order(持久化实体)
2 依赖方向约束
- Controller层只依赖Service层
- Service层只依赖Repository层
- Repository层只依赖数据源(数据库、缓存)
- DTO和Entity不能互相依赖
3 工具层面的保障
- 使用分层架构检查工具(如ArchUnit)
- 在代码审查中强制检查依赖方向
- 使用Maven/Gradle模块划分(如
api、service、repository)
常见问答(Q&A)
Q1:小项目也需要严格分层吗?
A:即使是Demo项目,也建议至少有“请求处理-业务逻辑-数据存储”的划分,不要因为项目小就纵容“全部代码写在一个文件”的做法,否则当项目变大时重构成本极高。
Q2:Service层能不能调用另一个Service?
A:可以,但要有节制,如果两个Service存在循环依赖说明设计有问题,最佳实践是:通过领域事件或应用层编排来解耦。
Q3:DTO和Entity为什么要分开?
A:DTO是面向传输的,会频繁变动;Entity是面向持久化的,与数据库结构强绑定,混在一起会导致:改前端字段时影响数据库表,或者改数据库结构时必须修改API文档,分开后,各层可以独立演进。
Q4:分层规范是否能防止所有“坏代码”?
A:不能,规范只是基础,还需要团队成员理解“为什么分层”,如果团队不了解SoC(关注点分离)原则,即使有规范也会写出“伪分层”代码——比如在Controller里写一堆工具类方法,或者在Service里写HTML片段。
代码分层规范不是一成不变的教条,而是指导我们如何组织代码、隔离变化、降低复杂度的工程思维,从项目第一天就建立分层意识,比后续重构要省90%的时间,记住三个关键词:职责清晰、依赖单向、边界分明。
如果你正在为“混乱的代码”烦恼,不妨从今天起,给你的项目画一个清晰的分层边界图。