关注点分离是什么
Dijkstra 在 1974 年提出:能同时把注意力集中在少数几件事上,是处理复杂性的前提。落到代码里就是把表现、业务规则、持久化与横切能力分别组织,让一个关注点变化时不必强迫其它关注点跟着改。它不是某一种架构,而是这些架构共同的判断依据:这条边界到底挡住了哪一类变化。
基本信息
| 提出 | Edsger W. Dijkstra(1974) |
|---|---|
| 典型形态 | 分层、MVC、模块化、AOP、六边形 |
| 收益 | 各关注点可独立理解、替换、测试 |
| 边界 | 关注点怎么切分随领域而变,没有统一分法 |
| 历史 | MVC 源自 Smalltalk-80 的界面实践,后被 Web 框架广泛沿用 |
典型使用场景
- Web 层把参数解析与业务规则分开,换接口协议不动规则
- 持久化细节收进仓储实现,业务代码里不出现 SQL 与连接管理
- 日志、鉴权、事务抽成切面或中间件,业务方法只留业务
- 前端把状态管理与渲染分开,换视图库不动数据流
- 构建脚本把依赖解析与发布动作分阶段,便于单独重跑
- 报表系统把取数、口径计算与呈现分开:换图表不改口径
横切关注点抽离
横切关注点抽离
// 之前:同一段事务与日志在 20 个 service 方法里各写一遍
public void transfer(Account from, Account to, Money m) {
log.info("start");
tx.begin();
doTransfer(from, to, m); // 真正的业务只有这一行
tx.commit();
}
// 之后:横切能力搬到切面,方法体只剩业务语义
@Transactional
@Loggable
public void transfer(Account from, Account to, Money m) {
doTransfer(from, to, m);
}形态与分离对象
| 形态 | 分离的关注点 | 常见实现 |
|---|---|---|
| 分层 | 表现 / 业务 / 持久化 | Controller-Service-Repository |
| MVC | 输入控制 / 数据 / 渲染 | 框架路由与模板引擎 |
| AOP | 横切能力 | 切面、中间件、装饰器 |
| 六边形 | 领域逻辑 / 外部适配 | 端口与适配器 |
| 事件驱动 | 触发方 / 处理方 | 消息中间件与订阅者 |
关注点边界常与团队边界重合:谁维护什么,往往决定代码里怎么切。组织调整后代码边界迟早跟着动,提前对齐能少返工;反过来,如果两个关注点由同一批人维护、改动节奏也一样,强行拆开只会增加同步成本。
分离不等于切碎。每多一层就多一次跳转,追一个请求要跨五层说明切过头了。判断标准是这条边界挡住了哪类变化、省下了多少联动修改,而不是层数或目录数好看。