写点什么

API 工具链研发的理论基础 - 流派

用户头像
李宇飞
关注
发布于: 2021 年 03 月 31 日
API 工具链研发的理论基础 - 流派

在乌托邦世界的理想国里,有一家企业,他提供的服务被世界上许许多多的客户使用着。人们都希望,能够使用自己趁手的工具/编程语言,来享受该服务带来的便利。


小欧是一个初入职场的年轻工程师,他怀着对前路的憧憬和对未来的迷茫加入了它,希望能帮助这家企业打造出好用的工具产品,满足用户的期待。


企业对外公开了大量的 API,用户通过自己趁手的编程语言来编写程序,编排 API,创建自己的需要的产品实例。


我们的故事,从小欧面临的第一个问题开始说起:API 是如何定义的。


源流


为了弄清楚这个问题,小欧研究了乌托邦世界中几乎所有的 API 设计工具,总结出了它们的一些共同的构成。


首先是结构类信息,包括 API 的:


  • 组织方式,如何划分命名空间,例如按照不同的产品将 API 的定义分开,甚至可以采用多级的命名空间划分,比如产品大类 - 产品小类等等

  • 抽象粒度,比如我们如果以一次 API 调用作为一个整体来看待的话,那么这些 API 应该如何分布在命名空间中?是以资源,还是以服务的形式来组织?和网络协议相关的声明(比如 HTTP 动词),应该在哪个层级中被定义?

  • 基本构成,包括 API 的请求、响应以及错误信息的定义


其次是特性类信息,一般指用于特种用途,主要由周边系统来消费的信息。例如,SDK 的包名、国际化(i18n)的文本、API 文档的告示等等。


通常情况下结构类信息统一在 API 管理平台中来维护。而特性类信息则通常用于周边的系统,可以在系统中进行标注,也可以从周边的系统中抽取过来。结构类信息与特性类信息呈正交关系,一类信息的缺失并不会对另一类信息产生影响。


最后是类型系统,即对于 API 的定义,如何标注可以使其描述请求的和响应的类型信息。类型系统的完备性直接决定了是否可以完成后续的制品(例如 SDK、工具产品)生成的工作,同时也对 API 的编写提供了一定的约束能力。


一个较为完备的类型系统应提供以下几种类型:


  • 基本类型(Base/Primitive Type)

  • 复合类型

  • 数组类型(Array Type)

  • 对象类型(Object/Record Type)

  • 联合类型(Union/Sum Type)(可选)


编者按:关于类型系统的知识,这里就不过多介绍了,感兴趣的读者可以看附录中的参考文献。


作为一个经验丰富的工程师,小欧觉得,采用更为主流的技术,从软件工程的角度来说更加稳妥。


小欧决定稳一手,先找个开源方案用起来。


抉择


在调研的过程中,小欧发现,企业内部似乎已经存在了多种 API 主流方案的流派,选择之旅,似乎在一开始就夭折了。


因为面前有两头拦路虎:


  • 描述能力:企业中有大量风格迥异的存量 API,无法放弃,单一开源工具的描述能力不足以覆盖这些企业定制化的情形,包括但不限于 RPC 风格的 HTTP API、自定义的错误码格式,以及对于类型系统的扩展需求(例如枚举值需要定义三要素、命名、值和描述信息)。

  • 约束能力:开源工具需要满足绝大多数人的需求,所以在约束能力方面往往比较宽松,例如许多工具支持将字段类型声明为动态类型或联合类型,而一些企业可能需要更严格的约束。


那么如何既拥抱主流的方案,又能够解决企业遇到的难题呢?经过科学的软件工程训练的小欧,自然想到了 SOLID 原则中的里式替换原则(Liskov Substitution principle)。


我们完全可以派生出一个完全符合企业现状的 API 声明格式,并且在其它的方案上实现一个转换逻辑,只要保证新的格式在我们关注领域的描述能力是主流方案的超集,那么在这个领域我们就可以新旧两种方案并存。我们当我们需要新方案的描述能力时,就可以切换到新方案去编写。


我们的小欧一拍脑袋,“嗨,这不难嘛,我也能写!”。


小欧花了 5 分钟时间,写下了这样的 API:


- namespace: ooo  services:  - name: myservice    apis:    - name: myapi      request:      - name: foo        type: string        format: uuid      response:      - name: bar        type: array        items: { type: string }      errors:      - code: 42        message: "cause by chaos monkey"      traits:        i18n: myapi    traits:      sdk: myservice
复制代码


编者按:文中示例仅供参考,实际生产中的用法因为需要兼顾一些工程细节,会显得更为复杂些


优雅清爽、足够简单,API 定义的问题真的就这样解决了吗?


此时的小欧所不知道的是,更大的难题正在向他悄悄袭来。


参考阅读


项目实践:



经典书籍:



课程讲义:


  • 《编程语言的设计原理》,北大熊英飞老师开设的一门课程,其中涉及了类型系统的理论基础


发布于: 2021 年 03 月 31 日阅读数: 15
用户头像

李宇飞

关注

还未添加个人签名 2016.08.23 加入

还未添加个人简介

评论

发布
暂无评论
API 工具链研发的理论基础 - 流派