什么是API——应用编程接口解释

247 阅读10分钟

开发人员使用应用程序编程接口来隐藏复杂性,组织代码,并设计可重复使用的组件。下面是你需要了解的关于API的内容。

术语API代表应用编程接口,这个概念适用于从命令行工具到企业代码、微服务云原生架构的所有地方。API是一个接口,软件开发者用它来与他们自己代码之外的软件组件或资源进行程序化的交互。一个更简单的定义是,API是一个软件组件的一部分,可以被其他组件访问。

除非你从头开始写每一行代码,否则你将与外部软件组件互动,而每一个组件都有自己的API。即使你真的从头开始写所有的代码,一个设计良好的应用程序应该有内部的API,以帮助组织代码,使其组件更可重用。

API是软件开发的一个关键概念,从简单的程序到最先进的设计和架构考虑。本文将帮助你了解API以及它们在软件开发中的应用。

软件开发中的API

API是一个软件程序中可以被其他程序访问的部分。 它是一个软件组件的外部区域。 由于这个原因,你可能会看到一个程序的API表面区域的参考。API表面区域是程序或组件的外部层,就像细胞的壁,如图1所示。

what is an api fig1 IDG

图1.一个应用程序组件及其API

当一个程序被另一个程序使用时,我们称第一个程序为提供者,第二个程序为客户。 提供者中可被客户访问的部分是API。 这种安排在几乎所有类型的软件应用程序和系统中都有。一致的是,API是客户对提供者进行呼叫的一种方式。API定义了一个已知的可允许的输入和相关的输出范围。 因此,API定义了与一个组件进行通信的协议。

除了最微不足道的软件,所有的软件都使用其他组件提供的能力。一个软件程序调用一个组件的API来访问它的能力。 除了使用其他组件外,大多数软件还被其他程序作为一个组件使用,如图2所示。

what is an api fig2 IDG

图2.多个组件通过其API进行交互

APIs vs. UIs

你可能会注意到API和用户界面(即UI)之间有一些相似之处。这是有道理的,因为两者都是接口。接口是与系统内部进行交互的一种方式。 一般来说,接口的工作是将内部功能简化并集中到对客户有用的形式。API和UI的不同之处在于,它们与不同类型的客户端对接。

在笔记本电脑上,用户界面由输入设备(如键盘和鼠标)和输出设备(如显示器和键盘)组成。 客户端是使用笔记本电脑的人。 除了操作系统之外,许多在笔记本电脑上运行的程序也呈现出一个用户界面,用户可以通过笔记本电脑的输入和输出设备与之交互。 例如,网络浏览器在屏幕上呈现出一组视觉元素,可以用鼠标和键盘来控制。

浏览器的API

现在,让我们来想想那个网络浏览器。 我们知道,浏览器是用来打开各种网页的。 大多数网页都加载了JavaScript作为其构成的一部分。 浏览器运行JavaScript来帮助显示页面。为了工作,JavaScript程序需要访问浏览器的功能。 在这种情况下,JavaScript程序是API客户端,浏览器是API提供者。浏览器是一个提供网页浏览功能的供应商,JavaScript程序通过编程接口,即浏览器的API来访问这些功能。

例如,如果你现在输入F12并打开一个JavaScript控制台,你可以输入一个小的JavaScript程序与浏览器的API进行交互。 如果你在控制台中输入清单1中的代码,你将开始看到输出。

清单1.在浏览器控制台中跟踪鼠标


window.onmousemove = function(e){console.log("mouse cursor:", e.clientX, e.clientY)}

注意,在你开始看到控制台输出后,你可以通过输入来取消这个设置。


window.onmousemove = null

这个例子的重点是,窗口对象是浏览器API的一部分。同时,onmousemove 函数(或方法)是窗口对象的成员。反过来,它也是窗口对象API的一部分。 所以,一旦你进入代码,你就可以开始看到API无处不在。 如果你想使用一个组件的功能,你可以通过组件的API来访问它。

嵌套的API

另一个观察结果是,API存在于程序的不同层次,并且相互包含。 窗口API在某种意义上是嵌套在浏览器API里面的。

让我们多想一想,浏览器是如何完成其工作的。这将有助于我们了解其他几种API。 首先,浏览器是如何知道鼠标的位置的? 它通过一个API向操作系统注册。 然后,操作系统加载一个鼠标驱动程序,它提供一个标准化的API来提供关于鼠标正在做什么的流式信息。(如果你继续挖掘,驱动程序本身最终依赖于低级别的硬件和软件接口--与UI和API一起的第三种接口)。

库、包和模块中的API

浏览器控制台是一个特殊的环境,因为所有的库都是由运行时环境预先加载的。 更常见的是,库是由程序员明确加载的。 加载的方式因编程语言而异,但只要你在输出中看到importinclude 、或require ,就意味着当前程序正在引用另一程序的API。

除了最微不足道的程序之外,所有的程序都是由语言级别的表达式和结构(如if's、循环和运算符)与对其他包中的API的调用共同组成的。 反过来,每个程序也是一个有可能被其他程序包含和使用的组件。

广义上讲,模块、包和库都是同一个概念:它们是可以被包含的代码集合。 它们公开可见的部分--类、对象、方法、函数、变量等的总和就是该集合中API的表面积。

远程API和微服务

在最高层次上,我们可以将API分为两种类型:本地和远程。远程API很有用,因为它们不需要更新客户端设备上的代码,它们可以独立扩展,而且它们呈现出一种标准化的API形式,只要经过授权,任何客户端都可以调用它。

一般来说,我们可以说远程API(也被称为服务)是强解耦的,并提供一个标准的协议(通过TCP的HTTP/S),无论其背后的实现堆栈如何,都可以工作。

让我们建立一个与远程API的快速交互。 再次在你的JavaScript控制台,输入清单2中的代码。

清单2.调用《指环王》的API


const fetchData = async () => {
  const rawQuotes = await  fetch('https://the-one-api.dev/v2/quote', {
  headers: {
    'Accept': 'application/json',
    'Authorization': 'Bearer xvi06TocPJvBmrQC4yZv'
  }
})

  const quotes = await rawQuotes.json();
  const quote = quotes.docs[Math.floor(Math.random() *  quotes?.docs?.length)];

  const rawCharacters = await   fetch('https://the-one-api.dev/v2/character?_id=' + quote.character, { headers: headers })
  const characters = await rawCharacters.json();
  const character = characters.docs[0];
  console.log(character.name + " said: " + quote.dialog);
};

fetchData();

如果你运行这段代码,你会得到一个控制台日志,类似的内容。"咕噜说。他们是年轻的。他们很温柔。他们很好。是的,他们是。吃了它们。现在的情况是,你创建了一个JavaScript程序,使用浏览器API(特别是fetch API),对住在the-one-api.dev 的服务器发出一个HTTP调用这是一个REST API,这意味着它遵循某些架构惯例。

微服务和API网关

微服务架构本质上是使用远程API来完成传统上由本地API完成的活动。微服务架构将一个应用程序分解为可远程使用的组件。

API网关的概念是微服务架构所特有的。 在API网关中,在网络上定义了一个单一的接触点,用于协调通往特定服务的路线。 这允许某些好处(如跨服务的认证和速率限制),因此作为一种接口的界面来运作。

远程API无处不在

互联网基本上是一个由交互式远程API组成的宇宙。 在设备上运行的所有东西都是本地API。 服务器是本地API的集合,它们共同提供远程API。 客户端是本地API的集合,它们共同消费远程API。 中间件是本地API的集合,它们既共同提供远程API,又共同消费其他远程API。

API和良好的软件设计

在所有的平台和语言中,都有不同的方法来控制什么是可见的,以及客户端代码如何使用它。API设计非常重视信息隐藏的理念,这是可维护的软件的关键所在。好的软件设计依赖于此。

我们的想法是编写软件组件,以最小的接触点完成对它们的所有要求。作为开发者,我们希望只提供关于组件内部工作的最基本信息。这个概念适用于从一个微小的函数--它的签名是一个写得很小的API--到强大的远程服务。

好的API是意大利面条代码的反面。 在意大利面条代码中,执行和依赖的流程非常难以遵循,这使得代码难以维护和调试。(这就是为什么GOTO被认为是有害的)。

在良好的API设计中,软件组件的行为很像机械组件。 它们在一个被充分理解的接口后面执行特定的工作。 你可以把组件作为一个单独的实体来处理。 汽车上的交流发电机只做一件事:它创造一个电荷。如果它发生故障,机械师可以隔离这个部件。 同样重要的是,汽车的其他部分只需要知道皮带正在绕着交流发电机的皮带轮转动。 在这个比喻中,皮带轮和交流发电机的电气终端将是交流发电机的API。

当然,隔离从来不是完美的。即使在交流发电机的情况下,皮带和张紧器的状况也会以重要的方式相互影响。 开发人员试图创建良好的组件、子系统和架构。我们这样做是为了控制软件中的主要对立面:熵和复杂性的力量。

将复杂性集中在组件中,并使其接口和协议尽可能简单,使我们的软件系统更容易管理。

总结

API对于良好的软件设计来说是必不可少的,它们在我们软件的不同层面上有一系列的化身。 当你在编写软件时,把你正在编写的代码看作是一个组件是很有价值的,它有可能在其他系统中重复使用。考虑你的组件的API的特点。 如果你这样做,你很可能会把注意力集中在一组有限的功能上,你会考虑API的表面积如何与其他组件互动。从关注点分离的角度来考虑,尽量只暴露你的组件的严格要求的信息。

使用精心设计的API可以使我们的软件由逻辑上不同的组件组成。 这些组件可以在相对隔离的情况下进行维护,并且它们背后的功能可以在不同的应用程序之间重复使用。