API难解释?这次用啤酒和积木来破局
API是我们一直在用的东西。尽管API无处不在,但许多人、甚至技术人员对于它们是什么及工作方式有着很模糊的理解。说真的,请你的同事马上解释一下API。如果对方立马说“API指应用编程接口。它是让软件应用程序彼此通信的接口......”我会请这个人喝啤酒。大多数人真的无法阐明API。
让我们改变这种情况。
“A”表示应用。
该术语的第一个部分高度依赖上下文。视具体的使用场景而定,“应用”实际上可以指很多东西:整个服务器、整个应用程序本身及其所需的数据或只是应用程序的一小部分。
不妨看看这些上下文:服务器、整个应用程序和应用程序的一小部分。我们先设想Web是联网服务器组成的庞大全球网络。互联网上的每一页都存储在这其中一台远程服务器上的某个地方,即位于远处的计算机,经过优化以处理向你的浏览器提供这个特定网站的请求。
因此,如果你在浏览器栏中输入www.github.com,Chrome、Firefox或Safari等浏览器向GitHub的服务器发送请求,服务器会礼貌地发回在本地计算机上显示页面及内容所需要的全部代码。浏览器收到此响应后,它会解释代码并显示页面。
服务器作为API:在你的浏览器(又叫客户端)看来,GitHub的服务器就是API。这意味着每次你访问Web上的页面时,都与某台远程服务器的API进行交互。此处的API与远程服务器不一样。相反,它是接收请求并发送响应的服务器的一部分。
整个应用程序作为API:初始调用时,GitHub服务器发送整个Web应用程序:表示结构(网站布局及外观)以及网站的所有内容。表示这部分基本上固定不变,作为HTML代码发送,由浏览器显示。内容(网站中包含的动态信息)作为数据发送,常常采用JSON格式,然后在页面上的适当位置加以显示。
所以如果我们看一下典型的GitHub页面,表示部分(比如顶部的导航栏、左边的用户照片和简介、中间固定的存储仓库)几乎保持一样。但那些绿色小方形表示每日GitHub活动量的方框呢?这会根据用户的贡献而变化。我们将项目工作推送到GitHub,然后检查以确保它已添加到简介页面上时,API告诉浏览器将今天的方形标成绿色、它到底应该用什么色度。但是,其他的一切保持不变。
不同类型的API让我们的浏览器可以调用特定类型的信息,只更新相关的数据,无需重新加载没有变的其他所有内容。
应用程序的一部分作为API:构建Web应用程序时,用之前就由组件来构建快得多、容易得多(并且常常更可靠)。设想一下,很可能有一个库、预制平台或XaaS来提供。
但是这些组件如何相互通信,以便作为一个统一的应用程序来执行?
“P”表示协议,“I”表示接口
API的应用端可能大不一样,但无论我们谈论什么样的上下文,API的最终任务仍然一样:沟通和协调。
API中的“P”即协议指确定彼此约定的方法,以便其他软件与特定的API联系,请求/接收来自它的相关信息。
接口指API的中间方面,充当让两个应用程序能够相互联系的实际功能。
因此从根本上说,API好比是两个软件之间的一种协议或契约,这个“粘合层”让它们能够对接、协同运行。实际上,API说“如果你给我这个指令,我会执行此操作/返回此信息。”
打个比喻,API好比微酿啤酒厂的啤酒水龙头。每个水龙头对应某一类啤酒,所以当你按下标有“Porter”的水龙头把手时,就知道你的杯里会灌满浓郁的麦香味啤酒,按下“Pilsner”会出来清爽的黄色啤酒。同样道理,请求API输出的客户端知道按下哪个数据“水龙头”以便获得所需的输出。比如说,Porter预计从porter水龙头出来,而不是别的水龙头。同时,用户甚至不必知道或关心水龙头内部的情况。可以重新排列队伍或优化产品(你提供的啤酒或应用程序),而不影响用户,因为接口仍然一样。
API不仅仅推送数据,还接受数据。这里啤酒比喻不恰当,因为啤酒是单向流动。因此,我们用另外的比喻来说明数据如何进入API。设想一下小孩子玩的形状分类器玩具。圆形、星形和三角形的拼块通过适当形状的开口插入;星形拼块只能通过星形孔插入。在API中,数据以一种定义的形式(比如圆形或三角形)来提供,只能通过相应的开口穿过接口。API要求是某种格式,拒绝不适合的数据。别试图将三角形数据放入到方孔。因此,客户端被迫按照API构建器的规范(即协议)来组织输入,该规范为事务设定了预期要求。
无论我们用什么比喻来解释API,API都好比是两个软件之间的协议或契约,说“如果你给我这个指令,并采用这种格式,我就会执行这个指定的动作或返回此信息。”
API作为产品
除了作为浏览器、服务器、软件和数据库之间交换信息的载体外,API还可以打包成产品来销售。比如说,Weather Underground售卖访问其天气数据API的服务。这是一组专用的URL,返回纯数据响应(这里是最新的天气预报),以便用来在你自己的应用程序中丰富数据。你不是得到Weather Underground在其自己的应用程序或网站上所用的表示结构,你构建自己的图形用户界面。
话虽如此,你绝对可以用浏览器向API发出请求,查看返回的数据,无论用不用GUI。由于请求数据的实际HTTP传输以文本形式发生,你的浏览器通常能够显示响应。比如说,你可以直接用浏览器访问GitHub的API,甚至无需访问令牌。以下是你在浏览器中访问GitHub用户的API路由时获得的JSON响应,不妨看看我的:
{ "login": "mgienow", "id": 19556217, "node_id": "MDQ6VXNlcjE5NTU2MjE3", "avatar_url": "https://avatars2.githubusercontent.com/u/19556217?v=4", "gravatar_id": "", "url": "https://api.github.com/users/mgienow", "html_url": "https://github.com/mgienow", "followers_url": "https://api.github.com/users/mgienow/followers", "following_url": "https://api.github.com/users/mgienow/following{/other_user}", "gists_url": "https://api.github.com/users/mgienow/gists{/gist_id}", "starred_url": "https://api.github.com/users/mgienow/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/mgienow/subscriptions", "organizations_url": "https://api.github.com/users/mgienow/orgs", "repos_url": "https://api.github.com/users/mgienow/repos", "events_url": "https://api.github.com/users/mgienow/events{/privacy}", "received_events_url": "https://api.github.com/users/mgienow/received_events", "type": "User", "site_admin": false, "name": "Michelle Gienow", "company": null, "blog": "", "location": "Baltimore, MD", "email": null, "hireable": true, "bio": "Front-end web developer & recovering journalist - I write web dev/JS/Node/Python @TheNewStack", "public_gists": 1, "followers": 11, "following": 2, "created_at": "2016-05-24T16:33:09Z", "updated_at": "2018-01-27T03:26:14Z" }
所以你访问我的GitHub页面时,它调用GitHub API,以获取显示页面的表示代码(HTML/CSS),并调用另一个GitHub API以获取对我来说独特的数据。还有针对其他API的另外几个调用,以获取页面其他区域中的内容。浏览器收到所有这些调用后,知道将数据插入到页面,生成最终的、统一的表示。
组合起来
基本上来说,任何一款可与其运行时环境明确分开来的软件都能成为API中的“A”。它本身也可能有某种API。比如说,假设你在代码中使用第三方库。一旦该库合并到你的代码中,就成为整个应用程序的永久部分。然而作为一个独特的软件,该库使用API(无需担心,API预先打包),以便与你的其余代码进行交互。
所以API可以是服务器、应用程序,甚至买卖的产品。这就是为什么API很难解释,即使对于每天接触API的人来说也是如此。
也许定义API本质的最恰当的方法是使用乐高积木。积木提供了一种简单且结构化的方式,让所有积木都以同样的方式拼接起来。同时,积木可能的组合无穷无尽。与之相仿,软件可以使用API来连接我们寻找的信息以及查看信息的接口,创建独特的服务组合,而这些服务共同形成一个应用程序。