第2章 核心概念与术语:ViewModel边界、状态所有权、隔离域、公共状态总线、副作用容器
本章明确定义构成跨模块状态隔离体系的五个核心概念,并围绕它们建立统一的术语框架。每个概念既是架构决策的原子单元,也是后续章节中分层策略、数据流设计和风险控制的讨论基础。理解这五个概念及其关系,是掌握整套隔离方法的前提。
核心要点:五个概念形成一个闭环——隔离域划定范围,ViewModel边界定义守卫规则,状态所有权确立归属,公共状态总线实现受控共享,副作用容器管理不可控操作。任何跨模块状态问题都可以用这五个概念拆解。
2.1 边界定义:ViewModel边界
ViewModel边界是跨模块状态隔离的第一道防线。它不是一个物理接口或抽象类,而是一组约定 + 校验 + 强制规则的组合,用于限定一个ViewModel可以访问哪些状态、可以被哪些外部模块订阅、以及状态变更的传播范围。
- 物理表现:在代码层面表现为模块级的
internal/package-private可见性 + 运行时边界检查。 - 核心规则:任何状态离开所属隔离域前,必须显式声明到公共状态总线;任何外部读请求必须经过总线代理。
- 违反后果:导致状态突变溯源丢失、跨模块耦合、难以测试和回滚。
鉴别技巧:在代码审查中,如果发现模块A直接调用了模块B的ViewModel内部方法或直接读取其LiveData/StateFlow,就说明ViewModel边界已被突破,需要重构。
2.2 分层策略:隔离域与状态所有权
隔离域是状态存在的容器,状态所有权是容器内每个状态片段的归属标签。两者共同构成分层策略的基础。
| 层次 | 元素 | 职责 | 示例 |
|---|---|---|---|
| 域层 | 隔离域 | 划定状态生存范围,禁止外部直接访问 | “用户模块域” |
| 归属层 | 状态所有权 | 每个状态片段有且仅有一个所有者 | “UserProfileViewModel” |
| 守卫层 | ViewModel边界 | 在域边界执行读写校验 | 边界守卫策略 |
分层原则:隔离域可以包含多个ViewModel,但每个状态片段必须明确归属于唯一的ViewModel。所有权不可模糊,不可共享。
常见误区:团队成员常把「隔离域」等同于「模块文件夹」,这是错误的。隔离域是运行时概念,不是编译期目录结构。同一个模块内可以存在多个隔离域,只要它们不共享可变状态。
2.3 组件职责:五概念职责矩阵
| 概念 | 核心职责 | 生命周期 | 跨模块可见性 | 错误处理角色 |
|---|---|---|---|---|
| ViewModel边界 | 守卫状态,阻止非法越域读写 | 与隔离域相同 | 对域外不可见 | 越界拒绝 + 日志 |
| 状态所有权 | 标记状态归属,确保单点修改 | 与ViewModel相同 | 仅通过代理暴露 | 所有权冲突检测 |
| 隔离域 | 提供状态容器和边界环境 | 模块启动 ~ 销毁 | 域间隔离 | 域故障熔断 |
| 公共状态总线 | 跨域状态发布 / 订阅 | 应用全局 | 全局可见 | 广播失败重试 |
| 副作用容器 | 统一管理网络、DB、定时器等副效应 | 与隔离域绑定或全局 | 通过总线回传结果 | 副作用超时兜底 |
2.4 数据流 / 控制流 / 信任链路
五个概念之间的交互遵循严格的信任链路:
- 数据流:状态 只允许 从「状态所有权」→「ViewModel边界」→「公共状态总线」→ 其他隔离域。不允许直接跨域推送。
- 控制流:动作指令从「外部」→「公共状态总线」→「目标隔离域边界」→「状态所有权」→ 执行。边界守卫在入口处校验权限。
- 信任链路:每个隔离域只信任自己的ViewModel边界和公共状态总线;不信任其他隔离域的任何直接调用。
// 伪代码:跨域状态读取的信任链路示意
// 不允许: ModuleA.viewModel.state -> 直接 -> ModuleB
// 允许: ModuleA -> 总线.read("user/name") -> 边界校验 -> 所有权返回
2.5 选型权衡
| 场景 | 推荐策略 | 备选方案 | 权衡点 |
|---|---|---|---|
| 同模块跨ViewModel | 共享隔离域 + 内部事件总线 | 直接依赖 | 隔离性 vs 开发效率 |
| 跨模块强一致状态 | 公共状态总线 + 状态所有权显式声明 | 全局单例 | 可追溯性 vs 性能开销 |
| 高频副作用(如位置上报) | 副作用容器 + 批量回写 | 分散在各ViewModel | 集中管控 vs 灵活性 |
| 遗留系统迁移 | 先建边界屏障,逐步收拢所有权 | 一次性重构 | 渐进安全 vs 周期长 |
决策建议:优先保证「状态所有权」清晰,再考虑「公共状态总线」的性能优化。所有权模糊是架构腐化的第一信号。
2.6 风险点
- 边界穿透:开发者为图方便直接调用其他模块ViewModel内部方法,导致边界名存实亡。
- 所有权漂移:同一状态被多个ViewModel修改,失去单一可信源。
- 总线过载:所有跨域通信都走总线,导致事件爆炸、调试困难。
- 副作用逃逸:副作用直接在ViewModel中执行,绕过容器管理,造成测试困难和内存泄漏。
- 隔离域泄露:隔离域内部状态通过回调或监听器泄漏到域外。
2.7 落地步骤
- 盘点现状:梳理当前模块间所有直接的状态读写依赖,标记越界点。
- 划定隔离域:按业务模块或功能簇划分隔离域,明确每个域的边界。
- 声明状态所有权:为每个状态片段指定唯一的所属ViewModel。
- 引入公共状态总线:建立跨域状态发布/订阅机制,替换直接依赖。
- 建立副作用容器:将网络、DB、定时器等统一收容到容器中。
- 添加边界守卫:在隔离域入口处增加运行时校验或编译期可见性限制。
2.8 验收标准
| 验收项 | 验证方式 | 通过条件 |
|---|---|---|
| 边界完整性 | 代码扫描 + 运行时日志 | 无直接跨域ViewModel调用 |
| 所有权唯一性 | 静态分析 | 每个状态字段仅被一个ViewModel修改 |
| 总线合规性 | 链路追踪 | 所有跨域读/写均经过总线 |
| 副作用归仓 | 单元测试覆盖 | ViewModel单元测试中无真实IO |
| 隔离域自愈 | 故障注入 | 单域崩溃不影响其他域状态 |
快速自检:如果团队新成员能在30分钟内说出当前模块的「隔离域划分数」「每个域的状态所有权归属」「总线使用的三个典型场景」,说明概念落地合格。
本章定义的五个核心概念将贯穿整个课程。第3章将在此基础上,展开分层状态架构的具体设计模式。