UI = f(statesⁿ)

现代 UI 工作常被概括为“UI = f(state)”,但开发者认为,真实应用——从 Web 前端到游戏——暴露出的状态比大多数模型承认的要更纠缠、更隐蔽。评论者分享了对状态机、事件流和确定性游戏逻辑的经验,争论“让非法状态不可表示”应严格到什么程度,并指出 React、LiveView 风格服务器或 XState 等工具如何帮助驯服复杂性,同时仍在同步、动画和多客户端行为方面留下空缺。许多人认为,游戏开发和形式化状态建模是更深入理解这些问题的宝贵实践。

游戏开发与状态建模

  • 几位评论者主张先做一些简单游戏(例如纸牌接龙、基础动作游戏),以便内化这样一个事实:每一种可见的可能性都必须在某处的状态中存在。
  • 即使是“简单”游戏,也很快会暴露出比最初图示多得多的状态,尤其是在网络、反作弊和回放/确定性方面。
  • 复杂的棋盘/卡牌游戏(例如 Wingspan、《万智牌》)被认为令人望而生畏;人们提到状态机、事件驱动编程、栈和规则文档,作为理解和建模这类系统的工具。
  • 对于确定性网络在多大程度上可实现存在争论,考虑到浮点行为、类似混沌的发散以及平台差异;锁步(lockstep)方案被认为很难但可行。

UI = f(state):优点与局限

  • 许多人原则上同意,视图是状态的纯函数;游戏、回放系统以及开发/调试视图被视为强有力的证据。
  • 也有人强调,“状态”必须包含中间/UI 专用状态:表单的部分输入、校验错误、加载标志、动画进度等。
  • 过度热衷于“非法状态不可表示”会损害 UX(例如在用户输入时就对无效邮箱大喊大叫);有人认为有用的状态不应被建模为非法。
  • 有人建议更清晰地区分:
    • 领域状态(已验证的数据),
    • UI 组件状态(用户此刻正在做什么),
    • 以及二者之间的映射。

事件、动作与状态机

  • 有人提议用事件流来思考:state = reduce(state, event)view = fn(state),并让处理器分发事件,而不是直接变异。
  • 也有人将其表述为 view, effects = fn(state, events) 或以 action 为中心的模型;批评者指出,这通常最终还是会回到状态机的表述。
  • 状态机以及相关工具/库反复被推荐,作为驯服复杂性的方法。

前端复杂度与架构

  • 浏览器应用被描述为多个本地事件循环加上远程/分布式系统,而与后端生态相比,工具链往往较弱、粘合性很强。
  • 像 React 这样的框架被认为擅长“state → DOM”,但并不负责完整的数据同步问题(实时、离线、协作);其他工具(查询、同步层)填补空白,但常常不够连贯。
  • 有人主张采用以服务器为中心的 / LiveView 风格方法,把大部分状态和渲染留在服务器端,以简化推理。
  • 加载/获取被强调为多状态问题(初次加载 vs 刷新 vs 追加),而那些区分“loading”和“fetching”的库受到称赞。

动画、过渡与隐式状态

  • 当数据在动画完成前就变化时,过渡/动画会挑战天真的“UI = f(state)”观点。
  • 建议的修复方式包括:把动画状态/进度显式建模为状态,或者依赖平台级声明式动画,同时把开始/结束状态保留在应用状态中。
  • 总体上,大家更倾向于:一切都是状态,但其中一部分是隐式的,或者由平台处理。