Skip to content

Hyrum 定律 = API 实际行为依赖 ​

解决什么问题:API 升级时总有用户被破坏—— Hyrum 定律指出 API 的"实际行为"包含所有可观察行为,不是文档说的。

业务问题 ​

真实场景 ​

场景 1:API"内部实现"变成"外部依赖"

python
# API 文档说:"返回的错误码是 INVALID_INPUT"
# 但用户代码:
try:
    result = api.create_order(...)
except ApiError as e:
    if e.code == "INVALID_INPUT":
        # 文档说这是 INVALID_INPUT
        retry_with_fix()
    elif e.code == "INVALID_INPUT_OLD":  # 旧版本代码
        # 没人说要支持这个,但总有人依赖
        log.warning("old code path")

问题:你只是改了错误码的拼写,用户代码全部崩了。

Hyrum Wright 原话:

"With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody."

失败模式 ​

失败模式后果
"只是实现细节"改了用户依赖了"实现细节"被破坏
错误码语义改变用户分支判断错
响应字段顺序改变用户反序列化失败
性能特征改变用户超时假设失效

控制论视角 ​

Ch 4 §4.6:"不变量必须被维护" + Ch 21:"实际系统的行为 ≠ 设计意图"

Hyrum 定律 = 控制论的"实际不变量"
  - 设计意图 ≠ 实际行为
  - 用户依赖 = 实际不变量
  - 改变 = 破坏不变量 = 违反契约
  
原则:
  - 文档说的 = 设计意图(不是 SSOT)
  - 用户依赖的 = 实际不变量(才是 SSOT)

对位:

  • API = 控制律的输入端口
  • 用户依赖 = 系统已知的反馈模式
  • 升级 = 改变控制律(必须考虑所有已知反馈)

核心概念 ​

Hyrum 定律 4 推论 ​

1. 所有可观察行为都是契约
   - 返回值
   - 错误码
   - 性能特征
   - 资源消耗
   - 副作用顺序

2. 用户越多 = 依赖越多
   - 用户数 ↑ → 行为不变 = 风险 ↑
   - 任何"小改动" = 大破坏

3. 隐藏行为 ≠ 没有依赖
   - 内部实现 = 用户也会读源码
   - "私有" ≠ "不被观察"

4. 弃用是唯一方案
   - 不破坏 = 不升级
   - 升级 = 弃用 + 迁移

应对策略 ​

策略 1:少暴露
  - 只暴露必要的行为
  - 隐藏实现细节
  - 内部 API vs 公共 API

策略 2:明确稳定层
  - 一级 API(承诺稳定)
  - 二级 API(可能变)
  - 内部 API(可随时改)

策略 3:弃用周期
  - 标记 deprecated
  - 给迁移路径
  - 监控使用
  - 关闭

策略 4:版本控制
  - SemVer
  - 重大变更 = Major
  - 多个 API 版本共存

工程实践 ​

决策 1:API 是 stable 还是 experimental? ​

判断标准:
  - 公开 API 给外部? → stable
  - 内部使用? → experimental
  - 会被引用多次? → stable
  - 一次性使用? → experimental

决策 2:如何处理"实现细节" ​

选项 A:完全隐藏
  - 用 private / internal 修饰
  - 文档不提及
  - 强制封装

选项 B:标记为"未承诺"
  - 文档说明"可能变化"
  - 但用户还是会依赖
  
选项 C:明确稳定
  - 承诺 = 必须维护
  - 选择更慎重

实战 1:API 设计原则 ​

原则:
  - 最小化 API 表面
  - 不可变数据结构
  - 显式错误码(不依赖异常)
  - 文档化所有行为(包括性能)
  - SemVer 严格

反模式 vs 正模式 ​

反模式正模式
"只是重命名"视为破坏性变更
"应该没人依赖"假设有人依赖
"快速修复"完整弃用周期
"改一下实现"改实现 = 改变行为 = 通知用户

性能指标 ​

指标衡量健康值
API 表面公共 API 数量< 100
破坏性变更频率每季度0(除非 Major 版本)
弃用完成率deprecated → removed100%
迁移时间用户迁移平均时间< Major 版本周期

边界判断 ​

何时用 SemVer(★ 强烈推荐) ​

  • 公共 API
  • 库 / 框架
  • 多用户依赖

何时可宽松 ​

  • 内部 API
  • 实验性功能
  • 一次性工具

何时升级 ​

当前升级到触发条件
自由修改SemVer多用户
无弃用周期4 阶段弃用大型项目

关键洞察 ​

  1. Hyrum 定律是分布式系统的工程现实——任何 API 一旦有用户 = 不可破坏。
  2. 文档说 = 设计意图,用户依赖 = 实际契约——后者才是 SSOT。
  3. 隐藏 ≠ 没有依赖——内部实现也会被读源码。
  4. 弃用比删除更难——但它是唯一的"无破坏升级"路径。
  5. 与 cybernetics 同构——Ch 4 §4.6 不变量边界 = 用户依赖的实际边界。

从名家方法论与工程化思路中蒸馏出自己的工程体系。