面向因果
面向因果指的是在建模时,以事件、事实、因果与裁决过程作为系统组织的最小基础。
这与面向对象形成对照:
| 面向对象 | 面向因果 |
|---|---|
| 以对象、类、方法为最小单元 | 以事件、事实、裁决规则为最小单元 |
| 自底向上:先划分对象,再处理事件流转 | 自顶向下:先定义事实如何形成,再派生表现 |
| 状态分散在对象私有空间中 | 状态由因果层派生,感知层只持有投影 |
| 空间结构:封装、继承、多态、组合 | 时间结构:事件→裁决→事实→传播 |
| 谁拥有什么? | 谁导致了什么? |
面向因果适用于那些需要长期运行、持续交互、不断吸收变化的系统。
面向因果采用关系本体论建模,而非状态本体论。
两层模型
系统被拆分为两个相互协作的层次:因果层与感知层。
因果层
因果层是系统的事件解释与裁决引擎。
因果层维护三类核心资产:
- 待裁决事件:进入系统、等待解释的语义事件
- 事实历史:已经被承认并进入历史的关系事实序列
- 裁决规则:解释事件、解决冲突、计算结果的规则集合
因果层建模的时候,永远要以“关系第一性“作为首要设计原则,即维护导致状态发生改变的规则,而不是状态本身。
感知层
感知层是世界事实的响应式投影。它负责:
- 消费事实并形成投影
- 检测外部变化并将其整理成语义事件
- 组织连续表现、局部反馈与用户体验
感知层可持有局部状态,例如页面展开、动画进度、通知是否已读、摄像机补间。这些状态是事实的派生,本身不构成世界事实。
感知层可基于预测先行呈现,以提升响应性。例如:
玩家按下攻击 → 感知层立即播放攻击动画(预测动画,不修改世界事实)
→ 上报 attack_requested → 因果层裁决
→ 因果层裁决后返回事实 damage_applied → 感知层修正表现(事实动画)
动画可以先行,但伤害、死亡等事实必须由因果层确认后才能真正生效。只有当局部状态可能影响未来世界事实时,必须通过语义事件提交给因果层裁决。
两层交互
外部输入 → 感知层检测 → 语义事件 → 因果层裁决 → 新事实 → 感知层消费 → 呈现给外部
在架构职责上,感知层不直接改写世界事实,只能通过语义事件请求因果层裁决;因果层不直接处理表现,只发布事实供感知层订阅。
边界判定
将功能归属到哪一层,可依据以下标准逐项判定:
- 是否影响未来的世界事实?
- 是否需要进入历史、被追溯或被多个节点共享?
- 如果丢失或回滚,是否会导致严重Bug?
更简洁的判定原则是:因果层处理离散的关系变化,感知层处理连续的投影与反馈。
判定维度
| 判定维度 | 因果层 | 感知层 |
|---|---|---|
| 权威事实 / 局部表现 | 需要集中裁决、可追溯、确定性 | 组件低延迟反馈、局部自治、可丢弃 |
| 因果裁决 / 状态投影 | 变化冲突多、需要解释成立条件与先后顺序 | 关系相对稳定、以当前局部快照和局部派生状态为主 |
| 时间顺序 / 空间组织 | 关注时序、窗口、并发、抢占 | 关注结构、布局、组合、层级 |
| 全局收敛 / 局部响应 | 所有节点最终必须面对同一事实版本 | 各节点可以暂时保有自己的投影与反馈节奏 |
因果层离散,感知层连续;因果层负责权威事实,感知层负责投影表现。
复杂系统映射
将上述维度应用到不同复杂系统中,可以得到以下映射:
| 场景 | 判断 | 解决方案 |
|---|---|---|
| 网络游戏战斗系统 | 事实权威高、全局一致性要求高、局部状态活跃 | 权威服务器做因果层;客户端做感知层与预测;确定性事件同步;临时状态窗口;GGPO / rollback |
| 电商订单系统 | 事实权威高、实时性中等、强可追溯 | Event Sourcing + CQRS;Saga / 工作流;最终一致性 + 补偿 |
| 实时协作白板 | 局部自治性高、全局一致性要求高、允许短暂不一致 | CRDT / OT 处理本地更新;中央服务维护规范历史与收敛;响应式 UI 订阅事实变化 |
| 传统 CMS 内容管理 | 局部状态密度高、因果密度低、事实权威中等 | 经典 MVC / CRUD;无需复杂因果层 |
常见误区
为保证同步而将全部状态纳入因果层,会导致因果层膨胀为新的状态中心,丧失分层意义。因果层应只维护关系事实的版本,感知层在版本之间自由插值与预测。
与其他概念的关系
- 因果层不等同于 Event Sourcing:Event Sourcing 的前提是事件已经是事实,系统只负责存储和回放。但因果层把事件当作需要解释的输入:事件可能冲突、可能无效,需要被规则裁决后才能成为事实。因果层可以使用 Event Sourcing 作为存储技术,但 Event Sourcing 本身不包含解释、裁决和一致性保证。
- 感知层不等同于 MVC 的 View:View 通常是被动的,而感知层还负责检测输入、切割事件、组织连续反馈,在不影响世界事实的情况下可以连续自治。
- 最终因果一致性不同于最终一致性:分布式里的最终一致性,可以允许短暂不一致,但最终趋同,强调的是状态;最终因果一致性中,每个参与者的事实投影允许不完全一致,但是所有参与者面对的是同一个事实版本,强调因果。
相关阅读
- 游戏架构实践:面向因果如何在游戏开发中具体应用。