模型与现实的差距 = 所有模型都是错的
解决什么问题:承认"模型永远不等于现实"——避免追求"完美模型"的执念,转向"在当前问题下选最合适的近似"。
业务问题
真实场景
场景 1:UML 类图与代码的偏离
开发初期画了详细的 UML 类图:
- 50 个类,30 个接口,复杂关联
3 个月后:
- 实际代码多了 20 个新类(业务发现)
- 删了 5 个旧类(业务调整)
- 改了 80% 的方法签名
→ "模型对,但代码不对" 或 "代码对,但模型过时"
→ 谁应该跟谁?都是错的场景 2:性能模型的失真
容量规划时计算:
- 平均请求耗时 50ms
- QPS = 1000
- 需要 50 个 worker
上线后:
- P99 延迟 800ms(不是 50ms)
- 实际需要 200 个 worker
→ "平均模型"忽略了长尾场景 3:业务流程的失真
业务流程图:清晰画了 5 个步骤
实际情况:用户走了 12 种不同路径
异常分支:永远画不完失败的典型做法
做法 1:追求"完美模型"
✗ "我们要建一个完整的领域模型,覆盖所有场景"
✗ 花 3 个月建模,再花 6 个月"补完"
后果:
- 模型永远补不完
- 业务已经变了做法 2:模型不变,代码"凑合"
✗ 业务变化了,模型不变
✗ 代码里加 if-else 处理变化
后果:
- 模型与代码不一致
- 模型失去指导意义做法 3:模型精度越高越好
✗ "99.99% 精度的预测模型比 80% 精度的更好"
后果:
- 99.99% 的模型可能在错误的方向
- 80% 的模型 + 人工判断 > 99.99% 的错误模型控制论视角
数学原型
钱学森《工程控制论》Ch 1 §1.4 工程近似:
"几乎可以肯定地说:只要加以足够精密的分析,任何一个物理系统都是非线性的。我们说某一个实际的物理系统是线性系统,其意思只是说它的某些主要性能可以充分精确地用一个线性系统加以近似地代表而已。并且,所谓'充分精确'的意思就是说:实际系统与理想化了的线性系统的差别,对于具体研究的问题来说已经小到无关紧要的程度。"
控制论解法
工程控制论的核心态度:
1. 任何真实系统都是非线性的
→ "线性系统"是近似,不是真实
2. 没有"绝对正确的近似"
→ 只有"对当前问题足够好的近似"
3. 近似是否成立取决于问题
→ 同一系统在不同问题下需要不同近似
→ 工程的态度:
- 选合适的近似,不要追求完美
- 标注适用范围,不要假设永远成立
- 接受偏差,监控实际值与业务的对应
| 控制论概念 | 软件工程 |
|---|---|
| 物理系统是非线性的 | 真实业务是复杂的 |
| "线性"是近似 | 模型是简化 |
| "充分精确" | "够用就好" |
| "无关紧要" | 不影响决策 |
| 适用范围 | 业务边界 |
核心概念
定义
模型与现实的差距:任何业务模型都是对现实的简化,不是现实的复刻。模型的"对错"取决于它在当前问题下是否"够用"。
关键属性
| 属性 | 含义 |
|---|---|
| 本质 | 模型是现实的简化,不是现实的复刻 |
| 判断标准 | "对当前问题足够好",不是"绝对正确" |
| 边界条件 | 模型有"适用范围",超出就失效 |
| 时间尺度 | 同一对象在不同时间尺度下需不同模型 |
| 常见简化 | 线性化、降阶、集中化、确定性化、定常化 |
模型的 5 种简化
| 简化 | 真实 | 模型 | 何时用 |
|---|---|---|---|
| 线性化 | 任何系统都含高阶项 | 忽略高阶项 | 平衡点附近的小扰动 |
| 降阶 | n 阶微分方程 | 只保留主导项 | 主导极点的频段 |
| 集中化 | 实际是连续场 | 用 ODE 近似 | 几何尺寸 << 波长 |
| 确定性化 | 实际有随机扰动 | 忽略扰动 | 扰动远小于信号 |
| 定常化 | 实际参数时变 | 用常数近似 | 变化缓慢的时段 |
建模前必须回答的 3 个问题
1. 模型给谁用?
→ 使用者关心的"精度"维度是什么
2. 模型的边界在哪?
→ 什么时候模型不适用
3. 模型失效时怎么办?
→ 回退到"更精确但更慢"的方法?
→ 直接放弃?工程实践
步骤 1:明确模型的"适用范围"
每个模型都应该标注"适用范围":
markdown
## 模型:缓存命中率预测
- 适用范围: 命中率 60-95%, QPS < 10w, 缓存大小 < 1TB
- 不适用范围: 命中率 < 30%(大量击穿), QPS > 100w(边际效应改变)
- 失效信号: 实际命中率持续低于预测值 5% 以上步骤 2:识别模型的"简化在何处"
每个业务模型都要明确"隐藏了什么":
| 业务模型 | 隐藏了什么 | 失效场景 |
|---|---|---|
| 数据库 ACID | 硬件可能失败、时钟可能漂移、网络可能分区 | 机房断电、NTP 不同步 |
| 微服务接口契约 | 网络抖动、GC 暂停、线程调度 | 跨机房调用、低峰期大 GC |
| CDN 缓存命中 | 缓存失效、源站故障、回源延迟 | 缓存集中失效、源站异常 |
| A/B 测试 | 用户行为复杂、受外部因素影响 | 节假日、新闻事件 |
| 容量规划 QPS × 耗时 | 流量突发、依赖故障、季节波动 | 大促、秒杀 |
| 测试覆盖 | 代码有无数种输入 | 测试用例没覆盖到的边界 |
步骤 3:监控"模型偏差"
每个核心业务模型都应该监控"实际值 vs 模型预测值":
例:缓存命中率预测
- 模型预测:75%
- 实际值:70%
- 偏差:-5%
- 阈值:偏差持续 > 5% → 触发模型重新校准
例:QPS 容量规划
- 模型预测:1000 QPS / 50 worker
- 实际值:1200 QPS 时延迟飙到 800ms
- 偏差:worker 不足
- 阈值:P99 延迟 > SLO → 触发扩容步骤 4:模型版本管理
每个模型的"版本"应该和"适用范围"绑定:
模型 v1.0:
- 适用范围:业务量 1k-10k QPS
- 假设:单机房、主从数据库
模型 v2.0(升级):
- 适用范围:业务量 10k-100k QPS
- 假设:多机房、分布式数据库
→ 模型升级 = 适用范围扩展 = 假设改变常见反模式
反模式 1:把模型当成真实
症状:
- "我们用 Transformer 做语义匹配" ≠ "机器真的理解语义"
- "我们有数据驱动决策" ≠ "数据真的能预测未来"
后果:被模型绑架,看不到偏差
正解:永远用"模型辅助判断",不用"模型替代判断"反模式 2:模型精度的无限追求
症状:
- "99.99% 精度的预测" > "80% 精度的预测"?
后果:
- 99.99% 精度可能在错误的方向
- 80% 精度 + 人工判断 > 99.99% 错误的预测
正解:精度够用就行("对当前问题足够好")反模式 3:不标注适用范围
症状:
- "这个模型对所有情况都成立"
后果:模型失效时无人知晓
正解:明确标注适用范围 + 失效信号反模式 4:不测试模型的失效边界
症状:
- 模型只在"正常情况"下验证
- 异常情况下从未测试
后果:异常情况模型失效,事故扩大
正解:主动测试边界(混沌工程)工程实例
实例 1:电商订单模型
模型:
- 订单状态:待支付 → 已支付 → 已发货 → 已完成
- 状态转换:单向,不可逆
隐藏的简化:
- 实际有 5+ 种异常状态(已取消、已退款、已拒收、...)
- 实际有"逆向"操作(取消订单 → 已取消 → 重新激活)
- 实际状态可能并发变化(用户同时支付和取消)
适用范围:
- 正常情况:95% 的订单走主流程
- 不适用:5% 异常订单
失效信号:异常订单率 > 10%实例 2:分布式系统容量模型
模型:
- Little 定律:并发数 = QPS × 平均耗时
- 1000 QPS × 50ms = 50 并发
隐藏的简化:
- "平均"忽略了长尾
- P99 延迟可能是 500ms(10 倍)
- 实际峰值并发 = 500
适用范围:
- 平均负载稳定
- 延迟分布均匀
失效信号:P99 延迟 > 平均 × 5性能指标
模型健康指标
| 指标 | 设计目标 | 衡量方法 |
|---|---|---|
| 模型偏差率 | < 5% | |实际值 - 预测值| / 预测值 |
| 模型覆盖率 | > 80% | 实际数据在模型预测区间内的比例 |
| 模型失效次数 | < 1 次/月 | 模型明显偏差的次数 |
| 模型重新校准频率 | < 1 次/季度 | 不需要频繁调整 |
监控设计
关键监控:
- 每个核心模型的"预测值 vs 实际值"
- 偏差率超过阈值 → 告警
- 模型偏差持续 > 7 天 → 触发模型 review
告警分级:
- P2:偏差率 5-10%
- P1:偏差率 10-30%
- P0:偏差率 > 30%(模型完全失效)调优策略
模型偏差率上升时:
1. 检查数据源是否变化(输入偏差)
2. 检查业务规则是否变化(业务偏差)
3. 检查假设是否仍然成立(边界超出)
4. 必要时重新训练 / 重新建模
模型完全失效时:
1. 立即回退到保守模型(如平均估算)
2. 人工干预关键决策
3. 启动模型重建流程边界判断
何时不用
场景 1:业务极简
- 业务流程简单(< 10 个状态)
- 没有复杂的边界情况
- 异常情况可穷举
→ 直接用代码表达业务,不用"模型"这个中间层场景 2:业务完全确定性
- 所有路径都已建模
- 没有不确定性
- 没有优化需求
→ 模型 = 代码,无须单独建模场景 3:业务创新期
- 业务模式在频繁变化
- 没有历史数据
- 模型无法稳定
→ 不要建模,先用反馈闭环积累数据与其他方法论的边界
| 相邻概念 | 区别 |
|---|---|
| 能控性 | 能控性判断"业务状态能否被干预";本方法论判断"模型能否反映现实" |
| 线性边界 | 线性边界判断"简化假设是否成立";本方法是更上层的"模型与现实差距" |
| 数据驱动决策 | 数据驱动是工具;本方法论是态度 |
何时升级(更精细的建模)
当以下情况出现时,考虑更精细的建模:
1. 模型偏差率持续 > 10% → 引入更复杂的模型
2. 业务量级跨越 → 重新评估模型适用范围
3. 业务模式变化 → 重新建模
4. 决策失误频繁 → 反思模型边界关键洞察
钱学森的态度:模型不是"对"或"错",而是"在这个问题下够不够好"。
"问题决定模型",不是"模型决定问题"。同一个物理对象,在稳定性分析中用线性模型,在大扰动分析中必须用非线性模型——因为问题变了。
承认"模型与现实有差距"是工程师的成熟标志。 追求"完美模型"是工程师的常见陷阱。
相关链接
IDDD 对位
- 模型 = 业务的简化 → 问题空间 vs 解决方案空间(Ch 2):模型聚焦 Core Domain
- 模型 vs 实现 → Module vs Bounded Context(Ch 9):BC 是模型边界,不是实现边界
- 模型验证 → 风险驱动架构(Ch 4):用风险识别核心模型
核心:模型 ≠ 现实——模型是业务视角的简化投影,BC 是模型的容器。