HackerTube ?

How To Design A Good API and Why it Matters

Google TechTalks在 YouTube 播放 ↗

字幕解读

Joshua Bloch 将 API 视为长期资产,强调设计者要通过用例和一页规格先想清楚概念,再尽早让真实用户写代码验证。API 应保持小而清晰,隐藏实现细节,命名一致并提供准确文档;拿不准的功能先省略,类型和参数次序要可预测。不可变性、失败快速暴露等选择需服务于调用者,而非仅方便实现者。

英文字幕轨道 · 引文按字幕原文展示,可点时间戳回看片段。

内容要点

  • API 很难在发布后修正,因此先写用例和规格,并尽早用真实客户端代码检验。
  • 小而一致的接口降低调用者的概念负担;隐藏实现细节并认真选择名称。
  • 文档、参数精度、不可变性和最小化功能都影响长期可用性。
视频章节 6
  1. API 的长期价值
  2. 先写规格再编码
  3. 设计 SPI 与接口形状
  4. 文档和命名
  5. 继承与契约
  6. 错误信息与类型精度
具体观点与证据 5

API 尚未实现甚至规格尚未定稿时,就应编写真实调用代码,用用例发现接口缺陷,减少实现错误设计的浪费。

持续编写客户端示例,而非把完整实现当作早期验证前提。

you should start before you've implemented the API
探索此观点 →

公开接口一旦被依赖就难以删除,所以对可选能力应克制,优先保留未来添加空间。

稳定公共 API 的兼容性约束,不是禁止任何版本升级。

not be able to take it out once you put it into an API.
探索此观点 →

模块能统一完成的工作不应要求每位调用者重复串联步骤;样板代码会复制错误并泄漏内部概念。

以输出 XML 的繁琐工厂与包装步骤为反例。

don't make the client do anything the module could do.
探索此观点 →

同时提供结构化数据访问,避免用户解析展示字符串,否则字符串格式会成为无法自由修改的事实接口。

以 Java 堆栈信息的字符串接口为例。

programmatic access to all data that is also available in string form.
探索此观点 →

看起来无状态的日期格式化器仍含内部可变状态,共享使用时会产生并发问题。

讲座所讨论的 Java 日期格式化 API。

feels like an immutable object, except that it has state inside it.
探索此观点 →
补充字幕原文 2

API 可成为组织的重要资产,设计错误会长期影响使用者。

APIs can be among a company's greatest assets

拿不准某项功能是否必要时,倾向于不加入接口。

When it doubt, leave it out.
解读边界

演讲提供的是通用 API 设计经验,具体取舍仍受语言、兼容承诺和调用场景影响;“三种实现”针对 SPI 设计,不能机械套用到所有 API。

相关视频与证据 5

区分范围小对象与小接口,不是同一个尺寸

Metz 谈类和方法的粒度,以及彼此知道得更少;Bloch 谈 API 暴露的功能范围,并建议拿不准时不加入。可以比较内部拆分与外部接口收缩这两个不同设计维度。

关联视频

RailsConf 2014 - All the Little Things by Sandi Metz ↗

演讲的核心建议是拆小类与方法,并降低组件彼此需要了解的内容。

make smaller things
▶ 0:54–0:58 · 观看片段
当前视频

How To Design A Good API and Why it Matters

拿不准某项功能是否必要时,倾向于不加入接口。

When it doubt, leave it out.

适用边界 更多小类不必意味着更好的公共 API;不能把两段合并成对任意粒度的越小越好。

边界的双重作用模块边界既保护演进,也冻结选择

Conway 演讲指出沟通成本越高,跨边界迭代越少;Bloch 指出 API 一旦有人使用就难以删除。合读可以把变更成本拆成跨团队协调和对既有调用方的兼容承诺,分别检查设计边界的代价。

关联视频

The Only Unbreakable Law ↗

沟通成本越高,共同迭代越少。

the higher the cost of communication the less iteration will happen there
▶ 27:06–27:16 · 观看片段
当前视频

How To Design A Good API and Why it Matters

已被采用的公开接口难以删除。

not be able to take it out once you put it into an API.

适用边界 组织沟通成本与公共 API 兼容性是不同约束,不能把所有接口稳定性问题归因于组织图。

原理与实例隐藏突变不会自动消除并发耦合

范畴论导论指出对象封装仍会隐藏突变与数据竞争;Bloch 用日期格式化器和可变尺寸对象说明外观简单的 API 也可能暗含共享状态,因此建议尽量不可变。

关联视频

Category Theory 1.1: Motivation and Philosophy ↗

隐藏在对象中的突变仍可能导致竞争。

They hide mutation – they mutate some state inside, right?
▶ 10:48–10:57 · 观看片段
当前视频

How To Design A Good API and Why it Matters

不可见的内部状态可能使共享使用破坏计算。

feels like an immutable object, except that it has state inside it.

适用边界 这不是宣称所有对象或可变 API 都不安全;需要明确所有权、生命周期和并发契约。

设计原则的具体化少即是少处理例外与纠缠

API 设计演讲建议不确定时删去不必要内容;Simple Made Easy 将简单解释为关注点不纠缠;两者共同强调减少使用者必须理解的额外选择与依赖。

当前视频

How To Design A Good API and Why it Matters

API 设计遇到疑问时可删去不必要内容。

When it doubt, leave it out.
关联视频

"Simple Made Easy" - Rich Hickey (2011) ↗

简单指关注点不纠缠,而非仅仅容易上手。

start seeing interconnections between things that could be independent
▶ 59:28–59:32 · 观看片段

适用边界 删减 API 选项只是一个设计手段;它不自动保证底层关注点已解耦。

接口设计的共同原则用小接口和深实现减少使用者负担

Bloch 建议 API 保持小而清晰,拿不准的功能先不加入;Ousterhout 的深模块则以简单接口承载大量底层功能。两者共同指向一种具体设计收益:把复杂实现留在边界之后,让调用者只需理解少量稳定概念。

当前视频

How To Design A Good API and Why it Matters

对 API 功能是否必要拿不准时,应倾向于先不加入。

When it doubt, leave it out.
关联视频

A Philosophy of Software Design | John Ousterhout | Talks at Google ↗

深模块以简单接口隐藏大量功能,降低使用者必须理解的细节。

very simple interface with a very large amount of functionality underneath it
▶ 14:24–14:29 · 观看片段

适用边界 公共 API 的功能取舍与内部模块深度是不同层级的设计问题;小接口本身不保证内部模块设计良好。

Hacker News 评论

查看 HN 原评论 ↗