分层架构

分层架构是所有软件架构的基础模型,是"稳定核心 + 可替换实现"的结构化设计方式。无论是 DDD、六边形架构、整洁架构,都可视为分层架构的演进形态。

第一性原理:变化隔离机制

本质机制:变化隔离

软件系统的根本矛盾是变化。分层架构的核心价值在于将变化限制在特定层内,阻断变化传播链。

未分层:变化A → 影响B → 影响C → ...(级联扩散,无法管控)分层后:变化X → 只影响相邻层 → 影响边界确定,可控可预测                          ↑                    (前提:边界未被破坏)

机制实现

分层架构通过以下约束实现变化隔离:

  1. 边界明确——每层有明确职责,不允许跨层交互
  2. 单向依赖——上层依赖下层,不存在反向依赖
  3. 接口抽象——层间通过预定义接口通信,隐藏实现细节

效果:变化被封装在单一层内,同层实现可互相替换而不影响调用方。

核心原则:若上层依赖下层内部实现细节,系统退化为紧耦合

边界

分层架构有效性依赖以下前提:

代价

分层架构存在固有代价:

代价影响
性能损耗每层调用增加延迟
复杂度增加需要管理更多接口和边界
过度工程化风险简单场景分层成本超过收益

分层模式:严格分层 vs 松散分层

核心定义

模式约束本质
严格分层只能调用直接下层链路依赖,逐层传递
松散分层可调用任意下方层跨越中间层,直达底层
严格分层:变化传播路径线性,可追踪松散分层:变化传播路径网状,不可预测

选择原则

权衡维度严格分层松散分层
核心价值变化影响可预测调用路径更灵活
适用条件依赖拓扑稳定优先性能/简单性优先
架构健康退化风险低退化/腐化风险高
维护成本高(需持续约束)低(依赖人工约束)

本质选择逻辑:当"变化影响可预测"更重要 → 严格分层;当"调用灵活性"更重要 → 松散分层

分层的目标

目标对应机制价值体现
关注点分离每层只关心本层的问题,不跨层思考降低复杂度
隔离变化变化被封装在层内,不跨层传播技术变化不影响业务
可替换性同层实现可互相替换,不影响调用方提高扩展性(可替换基础设施、可添加新表现方式)
可测试性业务逻辑可独立于外部依赖测试Domain 可做纯单元测试
可演进性基础设施可插拔,协议可适配系统能以最小代价适应前端、技术栈变化

分层架构的常见问题 & 反模式

污水池

本质:请求穿透多层但每层仅做传递,未执行实际业务逻辑。

判断标准:若大部分请求属于穿透式调用,说明分层不适合当前场景。

为什么会发生:①明知违规但图省事的认知捷径;②大部分请求属于CRUD穿透时,业务本身不需要分层,但团队出于惯性继续坚持;③解决污水池的方法是开放某些层,但这又破坏了层隔离,形成两难。

应对

层次过犹不及

问题:为追求"完美分层"增设过多层级,导致性能损耗和复杂度爆炸。

为什么会发生:①层级崇拜——认为"层数越多越专业";②忽视代价——每增加一层就增加调用延迟和复杂度;③完美主义倾向——追求"完美"设计来展示专业性,缺乏何时停止的判断标准。

改进:按变化速度而非物理层数分层,确保每层有足够职责以证明其存在的合理性。

贫血领域模型

本质:Domain 层仅有数据无行为,所有业务逻辑堆积在 Application/Service 层。

危害

为什么会发生:①面向过程思维惯性——大多数开发者从生涯开始就接触三层架构,没有机会使用继承和多态等面向对象特征;②数据库建模先入为主——对象被当作数据载体,而非行为封装体;③技术推力——早期规范和框架鼓励将对象当作数据载体;④便利性诱惑——把逻辑放Service层比塞进领域对象更简单直接。

应对:将业务规则下沉到 Domain,让领域对象自己管理自己的状态和规则。

基础设施反向依赖领域

本质:领域层依赖了具体技术实现,而非通过接口抽象。

危害

为什么会发生:①早期快速上线压力——业务逻辑直接依赖具体技术实现,省去接口抽象的额外工作量;②抽象逃避——在领域层定义接口增加前期复杂度,短期看不到价值;③依赖链反转正确做法要求先设计接口,但增加了初始设计成本。

改进:通过依赖反转

边界失效(越界访问)

本质:层间边界被打破,出现跨层调用或循环依赖。

危害:边界失效 → 变化传播失控 → 架构腐化。

为什么会发生:①新成员不了解层间依赖规则;②快捷方式诱惑——"直接绕过去更快";③缺乏检测工具——没有静态分析工具强制执行架构规则;④累积效应——一次越界导致后续效仿,边界名存实亡。

应对:使用 lint 工具构建静态架构规则,防止越界访问。

过度分层 vs 过度合并

极端表现后果
过度分层每层职责过小,调用链路过长性能损耗,调试困难
过度合并多个职责堆积一层紧耦合,难以变更

平衡原则:每层应有明确且足够的职责,层间接口应稳定且有意义。

架构选型指南

决策维度方向推荐分层程度
业务复杂度完整分层(Domain 稳定层关键)
业务复杂度轻量分层(避免过度工程化)
性能要求简化分层(减少调用链路)
变化特征核心业务稳定完整分层(保护稳定核心)
变化特征基础设施多变简化内部结构(可替换)

本质决策逻辑:分层程度 = f(业务复杂度, 性能敏感度, 需要保护的核心)

分层架构治理的核心问题

问题表现治理手段
越界访问上层直接调用非相邻下层内部实现静态分析工具检测调用链
循环依赖A→B→C→A依赖拓扑分析
反向依赖Infrastructure → Domain接口抽象 + 依赖反转检测
职责模糊某层仅做透传,无实质逻辑污水池检测(穿透比例)

测试策略

测试策略适用层级原则
API 测试Presentation无业务逻辑,只验证协议适配与序列化
集成测试Application编排多 Domain 服务,验证事务边界与流程
纯单元测试Domain业务规则核心,不依赖外部基础设施
Mock 测试Infrastructure技术实现多变,隔离外部依赖确保可替换

核心原则:测试策略取决于层内逻辑的可测试性变化频率——稳定层(Domain)应纯单元测试,易变层(Infrastructure)应与具体实现解耦。

架构模式对照

核心架构模式

架构核心思想依赖方向适用场景复杂度
分层架构UI → Service → DAO → DB(传统)
Presentation → App → Domain → Infra(现代)
上层→下层小型/中型项目、快速原型到业务分层低→中
六边形架构端口与适配器,内外分离外围→内核多前端、多数据源
整洁/洋葱架构业务规则居中心,万物依赖内向外围→内核复杂业务逻辑中高

关键区别

维度分层架构六边形/整洁架构
依赖管理上层依赖下层外围依赖内核
业务逻辑位置Service层Domain层(实体/用例)
基础设施位置DAO层Adapter实现
可替换性差,换DB需改Service好,替换Adapter即可
测试性需mock DAO可独立测试Domain

适用判断

核心目标:实现高内聚、低耦合,业务核心不依赖技术栈。

关联内容(自动生成)