移动/游戏
在 Apple 平台选择、审查或迁移应用架构时…
当需要为 SwiftUI 功能选择架构模式、划定模块与依赖边界、规划渐进式架构迁移,或审查状态归属与测试接缝时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Apple 平台选择、审查或迁移应用通用
解决思路
- 记录功能的状态所有者、输入、输出、依赖、副作用、导航交接和现有测试。
- 识别具体压力:复杂状态机、共享派生状态、依赖控制、功能组合、团队归属或 UIKit 导航。
- 选择能解决该压力的最小模式;写下它新增了什么、什么保持不变。
- 用一个垂直切片实现,注入依赖并使用可观察的状态转换。
- 运行现有行为测试,加上状态转换和依赖失败测试;若行为改变,恢复 fixture,修复最小边界,重跑后再迁移下一个切片。
- 模式选择:MV 用于 SwiftUI 功能状态和编排直接;MVVM 用于展示逻辑需要可独立测试的适配器;MVI 用于功能最好建模为显式状态 + intents + reducer/effects;TCA 用于许多可组合功能需要确定性 effects、依赖和测试;Clean Architecture 用于大型产品需要跨 domain/data/UI 的严格依赖方向;Coordinator 用于 UIKit 或混合导航需要独立流程所有者;VIPER 用于维护已有 UIKit 模块的既定 VIPER 边界。
- 当导航复杂度是压力时,将 Coordinator 与另一个状态模式并用;它不是领域/状态架构的替代品。
- MV 默认:保持视图为状态表达式,把业务操作放进可观察模型和注入的服务中。
- 当大量展示转换需要在不渲染的情况下测试且适配器有真实行为时,选择 MVVM。
- 当转换、非法状态和 effects 需要一条可审计的类 reducer 路径时,选择 MVI。
- 当功能组合、依赖覆盖、取消和确定性 effect 测试跨模块反复出现时,选择 TCA。
- 当独立领域规则和依赖方向在多个交付/数据层之间重要时,选择 Clean Architecture。
- 为 UIKit/混合路由归属、深层流程组合或视图控制器之外的条件导航添加 Coordinator。
- 将 VIPER 保留给兼容的遗留模块或有意迁移;不要习惯性地用它开始新的 SwiftUI 功能。
- 不要仅因为视图很长就升级架构;先提取子视图、服务和聚焦的可观察模型。
- 迁移时一次迁移一个功能边界:用测试和依赖/状态清单冻结行为。
- 在现有操作周围引入目标边界。
- 一次移动一个状态转换或依赖,不要同时重写 UI 和持久化。
- 每个切片后比较行为、导航、取消、错误和持久化结果。
- 只有在没有调用方或测试依赖旧路径后才移除它。
- 从 ObservableObject 迁移到 Observation 时,在替换包装器前保留相同的所有者和变更隔离。
- 从 MVVM 迁移到 MV 时,只有在视图绑定到相同模型/服务行为后才删除仅转发的 view-model 成员。
- 采用 TCA 时,包装一个功能的状态/actions/effects,并增量迁移依赖。
- 常见错误修复:模式按流行度选择 → 将其绑定到观察到的功能压力;view model 只转发属性 → 删除它并使用 MV;一个对象拥有导航、网络、格式化、持久化和 UI 状态 → 按职责和依赖方向拆分;TCA 或 Clean Architecture 应用于琐碎屏幕 → 从 MV 开始并保留升级接缝;Coordinator 用作状态架构 → 让它专注于路由/生命周期归属;一个功能内混合多种模式 → 定义一个本地状态/effect 模型并在功能边界迁移;大爆炸式迁移 → 移动一个经过测试的垂直切片并重跑相同的证明矩阵。
- 审查清单:选择由具体功能/团队压力证明;状态所有者、变更路径、依赖、effects 和导航所有者显式;依赖注入且可在测试中替换;模式成本与功能复杂度成比例;UI 机制、导航 API、隔离和测试语法路由到兄弟技能;迁移一次一个垂直切片地保留行为;每个切片后验证失败、取消、导航和持久化行为;不残留仅转发层或上帝对象。
适用边界 · 注意事项
- 不要仅因为视图很长就升级架构,应先提取子视图、服务和聚焦的可观察模型。
- 不要用 Coordinator 替代领域/状态架构,它只负责路由/生命周期归属。
- 不要在一个功能内混合多种模式,应定义一个本地状态/effect 模型并在功能边界迁移。