API设计:先思考再编码

API是定义应用程序接口的通用术语,换句话说,定义了用户(人或机器)如何与程序交互。在Web开发世界中,API通常是响应客户端结构化文本数据请求的网站端点集合。

Web开发人员广泛使用和讨论的另一个概念是RESTFul Web API。它由Roy Fielding定义为一种架构风格,在客户端和服务器之间提供良好的通信协议。它包含了一些约束:无状态通信,基础技术(通常为HTTP)的使用和超媒体作为应用程序状态的引擎的使用。换句话说,它提出了一些用于构建web API的模式。为了简单起见,在这篇文章中将Web API简称为API。

一个JSON值一千字
让我们看一个API响应的例子:


{
"data": [
{
"story": "Jonatas Baldin was writing a blog post.",
"created_time": "2017-15-01T00:02:57+0000",
"id": "624510964324764_1046909755418214"
},
]
}

这段JSON的数据是智能手机从Facebook API响应中收集的Facebook状态消息的示例。很漂亮,对不对?

现在想象你是Facebook的工程师,负责这个API。有天您突然决定将id字段名称更改为message_id。嗯,这个小的变化可能破坏Facebook。真的。依赖于先前定义的结构的所有设备现在都无法收集这个JSON响应,也就无法向用户显示任何内容。

好坏丑
一个坏的API设计迟早会造成各种麻烦:

1.没有一致性:一旦API增长,端点往往只是为了满足即时需求被创建。
2.难以扩展:在对端点进行故障排除时无法参考。
3.难学:消费使用数据和开发API会是一段陡峭的学习曲线。
4.性能问题:抛出未进行规划设计的API代码通常会长期产生性能瓶颈。
5.API往往是永恒的:第一次是让它就能正确的最好机会。

API是您的应用程序与其用户之间的合同。它不能突然改变,否则会导致那些已经调用它的客户端发生混乱,API不应该在没有预见性的情况下仓促建立。这就是需要设计的地方:创建一个规划或约定,用于构建对象,系统或可衡量的人类互动。

第一件事:让我们谈谈HTTP

在介绍API代码之前,让我们先看一下超文本传输​​协议HTTP,顾名思义,它是用于在网络上传输数据。它有一组关于客户端和服务器如何交换信息的规则。其主要组成部分有:

URL:您的资源在Web上的位置,您的端点的地址。一个示例是使用http://example.org/users列出您的用户。

请求方法:客户端希望在特定端点上执行的操作。GET 用于检索资源,POST创建一个,PUT 和PATCH 来更新现有的资源,DELETE删除东西。

头部Header:包含有关客户端或服务器的信息。例如:内容类型(格式)、方法、认证令牌和其他。

正文内容body:客户端与服务器之间发送和接收的数据。JSON是事实上的标准。

状态代码:一个三位数字,用于告知请求状态。总而言之,2xx 状态表示成功,4xx意味着客户端错误,5xx意味着服务错误。


让我们看一个HTTP请求/响应示例:


Client request:
GET /users/1 HTTP/1.1
Host: www.example.org/users

Server response:
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 19 Feb 2017 00:43:51 GMT

{
"id": 1,
"first_name": "Jonatas",
"fast_name": "Baldin",
"role": "Caker"
}

良好的API设计需要良好的规格

在设计API时,有一些规范可以帮助您。最常用的是使用纯JSON的Swagger、使用YAML表示法的RAML和支持markdown语法的API蓝图Blueprint。我喜欢上了后者:即使它是邻居新的酷孩子,它已经成熟足够和能够让人愉快的工作。这里会阐述为什么。

从官方网站上获得定义:

API蓝图(支持markdown语法)是简单的,并且可以在API生命周期的访问每个元素。它的语法简洁而富有表现力。使用API​​ 蓝图,您可以快速设计和创建API,或记录和测试已部署的任务关键型API。

它是一个开放源代码,专注于协作,易于学习和良好记录的规范,由Apiary创建,其核心是设计第一,周围有一些很棒的工具:从模拟服务器生成器到全功能生命周期解决方案。

除了蓝图,还有MSON(Markdown语法对象符号),它以人类可读的方式定义数据结构,不是手动编写端点的主体数据,而是在可重用对象中表示它们。

以下是您需要了解的信息:

API名称,描述和元数据:关于API和蓝图版本的一些描述。
资源组:相关资源组,比如Users。
资源:定义唯一资源,它的端点和操作。
参数:在端点中用于指定动态参数,如ID或查询搜索。
响应:内容类型,HTTP状态代码和主体数据。

除此之外,蜜蜂是一个协作平台,用于创建、呈现、测试和服务您的API。他们有一个免费的公共项目计划,你可以直接用你的GitHub帐户注册,以创建自己的设计。

这里是一个蓝图代码示例:


FORMAT: 1A
HOST: http://cakes.ckl.io/

# Cakes API
Cakes is an API used to store and consume information about the most loved Cakes here at Cheesecake Labs.
Cakes是一个API,用于存储和消费关于Cheesecake Labs最受欢迎的蛋糕的信息。

# Group Cakes

## Cakes [/cakes/]

### List all Cakes [GET]

+ Response 200 (application/json)

+ Attributes (array[Cake])

# Data Structures

## Cake (object)
+ id: `1` (string, required) - The unique ID of a Cake.
+ name: `Cheesecake` (string, required) - The name of a Cake.
+ rating: `5/5` (string, optional) - The rating of a Cake.

如果您访问上面这个项目,您将看到一个漂亮的页面。真棒是:自动为每个项目创建模拟服务器是 - 见这里,看到魔法吗?不需要代码它也工作。任何有HTTP和Blueprint基本知识的人都可以创建一个模拟API,并从客户那里获得反馈。

上面的例子很简单,可以通过get获得。您可以查看蓝图教程和文档以深入了解其语法,并在此处阅读规范。此外,这是一个开源项目 - 欢迎社区的任何贡献。

恭喜!现在你掌握了设计API所需的知识。但在你开始启动你的系统之前,这里有一些小提示:

该做什么和不该做什么

这里是简单设计规则和最佳实践:

1.将端点操作视为CRUD(L)操作
我们的/cakes/端点可能有创建,读取,更新,删除和列表操作。你可以使用HTTP动词和URL来构造这些动作,例如:
列表:GET /cakes/
创建:POST /cakes/
阅读:GET /cakes/1/
更新:PATCH /cakes/1/
删除:DELETE /cakes/1/

2.正确使用HTTP方法
GET是获得,POST是发布。如果你只是想要一个蛋糕的列表不要使用POST。

3.HTTP是有方法的,使用它们!
POST /cakes/createCake
你不需要在URL中指定操作,我们已经知道POST创建一些东西,所以createCake不需要包含create字眼。

POST /cakes/
更清晰的URL,也会告诉我们可能其他方法将按这种方式使用,如GET /cakes。

4.单数还是复数!

GET /cakes应该返回一个蛋糕列表,所以GET /cake/1应该返回第一个蛋糕,对吧?很不幸的是,不行。即使它在我们的语言是有道理的,它只会用更多端点搞乱客户端和开发人员。

5.搜索,排序,限制?使用查询参数!
此功能允许您指定一些过滤列表端点,这里是一个例子:
GET /cakes/?name=apple
如果实现,应该所有名称是苹果的蛋糕。

GET /cakes/?name=apple&rating=4
您也可以使用连接参数&,搜索apple和评级为4的蛋糕。

6.使用4xx返回错误。
每个人都憎恨HTTP响应状态代码是2xx,却返回一个错误的消息!使用正确的代码:
401:未经授权的访问,授权过程未正确完成。
403:禁止访问,客户端被授权,但是没有访问资源。
404:着名未找到,表示资源不可用。

7.请清楚地描述您的错误
当发生问题失败时,通知客户端发生了什么以及如何恢复。这里有一个很好的方法:


{
"error": {
"type": "Authentication Error",
"details": "Authentication could not be established with the given username and password",
}
}

大家都明白。


8.资源泪水对象类
API端点将使用资源表示进行响应。将这些资源当作对象类,然后在现实世界中代表事物。

相信我,使用设计第一的哲学将带给你更好的睡眠。这里有一些好的API优点:

与您的客户交谈:了解他们需要什么,而不是他们想要什么。没有客户端的API只是一个坏的API。

易于使用:端点,资源和输出数据应尽可能遵循相同的结构。

难以误用:如果发出了错误的请求,返回错误并提供信息。

简单是比复杂更好:简单的事情在每个方面都很容易。

在实现它之前使用你的API:创建一个模拟服务器来获得最终结果并演示。如果可以,与您未来的客户谈话并询问他们的意见。

有弹性:当发生崩溃时,告知为什么以及如何处理这种情况。

测试一切。为每个端点,方法,参数,输入和输出数据编写测试。

你的API是一种新的小语言,你必须教会其他人使用它。

API Design: Think First, Code Later | Cheesecake L