6-14.【架构设计】在大型App中,全局State一定是反模式吗?什么情况下是灾难,什么情况下反而是最优解?

5 阅读3分钟

“全局 State 是不是反模式”本身就是一个误导性命题——真正的问题不是 全不全局,而是:

谁能改?怎么改?改了谁会受影响?


一句话结论(先给判断)

全局 State 本身不是反模式,
“可被任意修改的全局 State”才是。


一、为什么“全局 State”会被骂成反模式?

因为历史上它常常长这样👇

Singleton
 ├── 登录状态
 ├── 用户信息
 ├── 配置
 ├── 缓存
 ├── UI Flag
 └── 谁都能改

灾难不是“全局”,而是:

  • ❌ 修改入口无限多
  • ❌ 修改路径不可追踪
  • ❌ 没有边界、没有 owner
  • ❌ 改一个字段,全 App 都可能炸

二、什么情况下“全局 State = 灾难”?

1️⃣ 它承载“局部业务状态”

AppState.currentEditingPost
AppState.currentTab
AppState.isKeyboardVisible

❌ 这是典型灾难:

  • 生命周期短
  • 强 UI 相关
  • 与 Feature 强耦合

👉 本该是 局部 State,却被放成全局


2️⃣ 多个 Feature 直接读写

Feature A → 改
Feature B → 也改
Feature C → 监听副作用

结果:

  • 无法预测调用顺序
  • 并发条件竞争
  • Bug 难复现

3️⃣ 缺乏单向数据流约束

GlobalState.user = ...

谁改的?为什么改?什么时候改?

👉 调试直接进入“上帝模式”


4️⃣ 被用作“方便的捷径”

“先放全局,后面再重构”

这是大型 App 里技术债最凶的起点之一


三、那什么时候“全局 State”反而是最优解?

关键一句话:

当 State 的“语义就是全局的”,并且“变化路径是严格受控的”。


✅ 情况一:真正的 App 级事实(App Facts)

例如:

  • 登录 / 登出状态
  • 当前账号
  • Feature Flag / AB 实验
  • 语言 / 地区 / 时区
  • 远程配置版本

它们的特点:

  • 生命周期 = App 生命周期
  • 所有 Feature 都“合理依赖”
  • 改变时需要全 App 响应

👉 不全局反而更怪


✅ 情况二:只读为主、极少修改

读:高频
写:低频、可控

例如:

  • 配置
  • 权限矩阵
  • Capability 描述

👉 风险不在“读”,而在“写”。


✅ 情况三:有唯一写入口(极重要)

Action → Reducer → Global State

例如 TCA:

struct AppState {
    var auth: AuthState
    var settings: SettingsState
}
  • Feature 只能发 Action
  • 不能直接改 State

👉 全局 ≠ 失控


✅ 情况四:跨 Feature 协调状态

例如:

  • Deep Link
  • Push 跳转
  • 全局错误处理
  • Session 失效

它们天然是:

“一个事件 → 多个 Feature 联动”


四、判断一段 State 是否“该全局”的工程标准

你可以用这 4 个问题来问自己:

✅ 1️⃣ 生命周期是否 ≈ App 生命周期?

  • 是 → 倾向全局
  • 否 → 局部

✅ 2️⃣ 是否有“唯一可信来源”?

  • 是 → 可全局
  • 否 → 拆分

✅ 3️⃣ 修改是否必须可审计?

  • 是 → 强制单向数据流
  • 否 → 风险高

✅ 4️⃣ Feature 是否可以“只读”?

  • 可以 → 风险低
  • 必须写 → 需要边界

五、正确的“全局 State”长什么样?

✅ 好的全局 State(工程级)

struct AppState {
    var auth: AuthState
    var config: ConfigState
    var environment: EnvironmentState
}
  • 分域
  • 不承载 UI 细节
  • 不承载瞬时状态

❌ 坏的全局 State

struct AppState {
    var currentTab
    var isModalPresented
    var editingText
}

👉 UI 生命周期 ≠ App 生命周期。


六、SwiftUI / TCA 里的真实结论

全局 Store 是 TCA 的优势,而不是缺陷。
真正危险的是:没有 scope 的全局 Store。

scope(state:action:) 的意义不是解耦 View,
而是 给全局 State 划出“局部可见性”


最后一句话(架构级)

“全局”不是罪,
“无边界、无约束、无责任人”的全局,才是。