1. 单一职责原则核心解读:职责定义、变化轴线、内聚性度量
单一职责原则(Single Responsibility Principle, SRP)是模块化设计的基石。它不仅仅是“一个类只做一件事”,更核心的思想是“一个模块只应对一个变化原因”。本章将为你建立关于职责边界、变化轴线与内聚性度量的完整认知模型,为后续 Android 模块设计打下坚实的理论基础。
1.1 边界定义:职责即变化原因
Robert C. Martin 将 SRP 精炼为:“A class should have only one reason to change.” 在模块设计中,“职责”的准确定义是“变化的原因”。如果两个职责因为不同的原因而变化,它们就应该被划分到不同的模块边界中。
核心判断标准: 问自己“这个模块有多少个不同的角色(Actor)会对它的行为提出变更需求?” 答案就是它应该被拆分的数量。
| Android 组件 | 混合职责(违反 SRP) | 变化影响 |
|---|---|---|
| Activity | 生命周期管理 + 网络调用 | 配置更改或 UI 调整会破坏数据获取逻辑 |
| ViewModel | 状态持有 + 数据转换 | 业务规则变化导致 UI 状态逻辑变化 |
| Fragment | UI 渲染 + 业务逻辑 | 设计变更与功能变更高度耦合 |
1.2 变化轴线与分层模型
变化轴线是系统演进的维度。在 Android 分层架构中,每一层都对应着一条核心变化轴线,SRP 要求我们沿着这些轴线划分模块边界:
- 展示层(View/ViewModel): 变化轴线为 UI 框架与交互模式(如从 XML 迁移到 Jetpack Compose)。
- 领域层(UseCase/Entity): 变化轴线为 业务规则与领域逻辑(如促销策略调整)。
- 数据层(Repository/DataSource): 变化轴线为 数据源与存储实现(如从 SQLite 迁移到 Room)。
这种划分直接决定了数据流/控制流的方向:控制流从外层流向内层,但信任链路(依赖方向)通过接口反转,使得内层模块独立于外层的变化,从而彻底贯彻 SRP。
1.3 内聚性度量:模块质量量化
内聚性衡量模块内部元素之间的功能关联程度。SRP 要求模块具有高内聚性。LCOM(Lack of Cohesion of Methods)是常用的度量标准,高 LCOM 值意味着方法之间共享字段少,职责不单一。
低内聚性示例(违反 SRP):
// 混合了网络逻辑与存储逻辑,两个不同的变化原因
class UserManager {
fun login(user: User) { /* 网络逻辑 */ }
fun saveToken(: String) { /* 本地存储逻辑 */ }
fun updateProfile(user: User) { /* 网络逻辑 */ }
fun readToken(): String { /* 本地存储逻辑 */ }
}
// 问题:网络和存储逻辑混合,有两个不同的变化原因
高内聚性示例(符合 SRP):
// 所有方法都围绕“用户数据操作”这一个职责
class UserRepository(
private val api: UserApi,
private val storage: UserStorage
) {
fun login(user: User) = api.login(user)
fun updateProfile(user: User) = api.updateProfile(user)
fun saveToken(: String) = storage.save()
fun readToken(): String = storage.read()
}
// 优势:数据源变化只需修改 Repository 内部实现,对外接口稳定
工程建议: 在 Code Review 中,若发现一个类包含多个不相关的字段组或方法簇,即可判定 LCOM 偏高,需要应用 SRP 进行拆分。
1.4 选型权衡与风险点
应用 SRP 需要在粒度上进行权衡,过度或不足都会引入风险:
- 过度拆分(微模块地狱): 接口数量激增,组合成本高,调试和跟踪数据流变得困难。
- 过度合并(上帝模块): 职责混杂,导致模块难以测试、复用受限,一处变更可能引发多处连锁反应。
风险点: 在没有深刻理解领域上下文的情况下,盲目照搬 SRP 会导致不必要的复杂性。架构师必须根据业务稳定性和变化频率来动态判断拆分粒度,做到“恰到好处”。
1.5 落地步骤与验收标准
将 SRP 应用到 Android 模块设计中,可以遵循以下步骤:
- 识别变化轴线: 与领域专家协作,列出模块在未来迭代中可能发生变更的所有维度。
- 定义模块边界: 根据变化轴线,将系统划分为若干个高内聚的模块,确保每个模块只对一个轴线负责。
- 建立信任链路: 通过接口隔离(依赖倒置)定义模块间的契约,使得控制流与依赖方向分离。
- 度量与重构: 定期使用 LCOM 等指标量化模块内聚性,对评分异常的模块进行重构拆分。
验收标准:
- 模块对外只提供一个明确的职责定义(变化的理由)。
- 针对单一需求的变更,代码修改范围被限定在唯一的模块内。
- 模块内部实现了高内聚,所有方法和字段都服务于同一个领域目标。
核心思想: 单一职责原则不是约束,而是架构工具。它帮助我们在复杂系统中找到高内聚、低耦合的模块边界,从而降低维护成本,提升迭代效率。