About Api Design

less than 1 minute read

漫谈 API 设计

本文主要是个人对 API 设计的想法,欢迎讨论。

概述

一个系统的 API 设计能反映出系统的架构,好的设计往往能让 API 使用者快速上手,接触不久就能够“猜”出想要使用的功能在哪里,“猜”出每个参数的目的与使用方法。

这里的“猜”并不是毫无根据的猜测,而是这个人的在技术领域的知识积累与经验起到作用。

抽象极端

极端例子:小明设计了一个通用性很高的宇宙无敌 API

  void* do(void*);

只要定义好参数与返回值,这个 API 等效于目前世界上存在的所有 API ,同时也能用这一个 API 作为多个 API 的整合,最终这一个 API 就能作为任何复杂系统的 API 设计了。

不过,你如果真这么设计,会被使用者打,或者根本没有使用者。

另一个例子:需求是需要实现被加数为 1-9 的加法函数,小明想到一个设计

  int add1(int a);
  int add2(int a);
  ...
  int add9(int a);

没错,这个设计完美的实现了需求。

不过,你如果真这么设计,还是会被使用者打,或者根本没有使用者。

这两个例子很明显,可能大家会觉得自己不会做出这样的事情,不过这类事情就会发生在你或你的身边。

一个是过度抽象,另一个是导致更具体。

“过度抽象”与“太具体”之间有很大的间隙,这个间隙间,有时候很难判定一个设计是好是坏,每个开发人员/ API 设计者都有自己的喜好倾向,不同人所看到的同一个设计会有不同的评价。

好的设计

API 设计是为使用者服务的,设计者是乙方,使用者是甲方;设计者是产品经理,使用者是用户;

产品经理要让产品解决用户某些需求的同时,要提高产品的易用性。

一个系统或者说一个设计,肯定是为了解决某些需求的,为了解决某些需求,使用方想通过使用 API 解决需求,这个 API 的正确使用方法是与需求有关系的。

定义

下列定义可能不严谨,但凑合着看吧。。。

Rsys: 系统需求:系统本身能够完成的功能需求
Rapi: 系统 API 需求:系统对外开放的接口需求
Learn(Rsys): 学习系统功能实现所需的努力程度
Learn(Rapi): 学习系统 API 使用方法所需的努力程度

假设对于所有满足 Rapi 的集合为 S_Rapi = { api_x | x 取值 1-n,api_x 表示第 x 个元素 } 总共有 n 种方法设计(实际上 n 可能为无限大)。

理论 1 接口比实现细节简单

  Learn(Rsys) > Learn(Rapi)

一般来讲系统 API 学习会比实现系统要简单,如果不是,那就没有必要做 API 。

理论 2 实际的接口设计会带来额外的复杂度

  Learn(api_x) > Learn(Rapi)  对 x 取值 1-n 有效

无论系统 API 最终怎么设计,最终不会比系统 API 需求的复杂度等级低

所以,复杂度有下限,无法设计出更简单(复杂度低)的 API ,如果能,肯定是砍了一些需求。

理论 3 如果某种 API 设计比自己实现起来还复杂,那就别用了

  如果 Learn(api_x) > Learn(Rsys) ,那么 api_x 很失败。

如果自己实现一个系统的难度比学习这个系统的某个 API 实现 api_x ,那么这个 api_x 非常失败。

这种情况下,使用者还不如自己实现系统需求。

理论 4 好的 API 设计的复杂度会小

  当 x = k 时,能让 Learn(api_x) 最小,那么这是最好的设计

因理论 2 可以得出

  当 x = k 时,能让 Learn(api_x) - Learn(api) 最小,那么这是最好的设计

即,能让 API 设计实现带来的额外复杂度越小越好。

Updated: