API 设计最佳实践

  2016 年 10 月 10 日

对于那些试图完善其 API 策略的团队来说,良好的 API 设计是一个经常被提及的话题。 在之前的博客文章中,我简要讨论了API 设计的重要性。精心设计的 API 的好处包括:改进的开发者体验、更快的文档和更高的 API 采用率。 但是,究竟什么才算良好的 API 设计?在这篇博客文章中,我将详细介绍一些设计 RESTful API 的最佳实践。

精心设计的 API 的特点

一般来说,有效的 API 设计应具有以下特点:

    • 易于阅读和使用:精心设计的 API 将易于使用,并且其资源和相关操作可以被经常使用它的开发者快速记住。
    • 难以误用:实现和集成良好设计的 API 将是一个简单的过程,并且编写不正确的代码的可能性会降低。它具有信息丰富的反馈,并且不对 API 的最终用户强制执行严格的指导方针。
    • 完整且简洁:最后,一个完整的 API 将使开发者能够针对您公开的数据制作功能齐全的应用程序。完整性通常是随着时间的推移而实现的,大多数 API 设计者和开发者会逐步构建在现有 API 之上。这是每个拥有 API 的工程师或公司都必须努力实现的目标。

为了说明下面列出的概念,我将以一个照片分享应用程序为例。该应用程序允许用户上传照片,并使用拍摄照片的位置和描述与之相关的情绪的标签来对其进行表征。

集合、资源及其 URL

了解资源和集合

资源是 REST 概念的基础。资源是一个重要到足以在自身中被引用的对象。资源具有数据、与其他资源的关系以及对其进行操作的方法,以允许访问和操作相关信息。 一组资源称为集合。集合和资源的内容取决于您的组织和消费者需求。例如,如果您认为市场将受益于获取有关您产品用户群的基本信息,那么您可以将其作为集合或资源公开。 统一资源定位符 (URL) 标识资源的在线位置。此 URL 指向您的 API 资源所在的位置。基本 URL 是此位置的固定部分。 在照片分享应用程序中,我们可以通过集合和资源公开有关使用该应用程序的用户的数据,并通过适当的 URL 进行访问。

  1. /users:用户集合
  2. /users/username1:包含有关特定用户信息的资源

名词更好地描述 URL

基本 URL 应该简洁、优雅且简单,以便使用您产品的开发者可以在其 Web 应用程序中轻松使用它们。冗长且难以阅读的基本 URL 不仅难看,而且在尝试重新编码时也容易出错。应该始终信任名词。 没有关于保持资源名词单数或复数的规则,尽管建议保持集合为复数。为保持一致性,分别在所有资源和集合中保持相同的复数形式是良好的实践。 保持这些名词不言自明有助于开发者从 URL 中了解所描述的资源类型,这最终可以使他们在使用您的 API 时能够自给自足。 回到照片分享应用程序,假设它有一个公共 API,其中 /users 和 /photos 作为集合。请注意它们都是复数名词吗?它们也是不言自明的,我们可以推断出 /users 和 /photos 分别提供有关该产品注册用户群和共享照片的信息。

使用 HTTP 方法描述资源功能

所有资源都有一组可以对其进行操作的方法,以使用 API 公开的数据。 RESTful API 主要由 HTTP 方法组成,这些方法针对任何资源具有明确且唯一的操作。以下是定义 RESTful API 中任何资源或集合的 CRUD 操作的常用 HTTP 方法的列表。

方法 描述
GET 用于检索资源的表示形式。
POST 用于创建新的资源和子资源
PUT 用于更新现有资源
PATCH 用于更新现有资源
DELETE 用于删除现有资源

(如果您想知道 PUT 和 PATCH 之间的区别,请查看 StackOverflow 上的此帖子。) 最好不要在 URL 中使用动词。GET、PUT、POST 和 DELETE 操作已经用于对 URL 描述的资源进行操作,因此在 URL 中使用动词而不是名词会使资源的使用变得混乱。 在照片分享应用程序中,以 /users 和 /photos 作为端点,您的 API 的最终用户可以使用上面描述的 RESTful CRUD 操作直观地使用它们。

响应

提供反馈以帮助开发者取得成功

向开发者提供关于他们如何使用您的产品的良好反馈,对于提高采用率和留存率大有裨益。 每个客户端请求和服务器端响应都是一条消息,在理想的 RESTful 生态系统中,这些消息必须是自我描述的。 良好的反馈包括对正确实现的积极验证,以及关于不正确实现的翔实错误,可以帮助用户调试和纠正他们使用产品的方式。对于 API,错误是为使用 API 提供上下文的好方法。 围绕标准 HTTP 代码调整您的错误。不正确的客户端调用应具有与之相关的 400 类型错误。如果存在任何服务器端错误,则必须将适当的 500 响应与之关联。对您的资源使用的成功方法应返回 200 类型响应。 有很多响应代码。有关其他信息,请查看此 REST API 教程 一般来说,使用您的 API 时有三种可能的结果:-

  1. 客户端应用程序行为错误(客户端错误 - 4xx 响应代码)
  2. API 行为错误(服务器错误 - 5xx 响应代码)
  3. 客户端和 API 工作正常(成功 - 2xx 响应代码)

当您的最终用户在使用您的 API 时遇到障碍时,引导他们走向成功,对于改善开发者体验和防止 API 误用大有裨益。很好地描述这些错误响应,但要保持简洁明了。在错误代码中提供足够的信息,以供最终用户开始修复原因,如果您觉得需要更多信息,请提供指向其他文档的链接。

为您的所有 GET 响应提供示例

精心设计的 API 还有一个示例,说明在针对 URL 成功调用后可以期望获得的响应类型。此示例响应应简单、清晰且易于理解。一个好的经验法则是帮助开发者在五秒钟内准确了解成功响应会给他们什么。 回到我们的照片分享应用程序,我们定义了 /users 和 /photos URL。/users 集合将以数组形式提供所有在应用程序中注册的用户的用户名和加入日期。 您可以使用 API 设计工具在 Swagger (OpenAPI) 规范中定义您的 API,如下所示:

responses:
        200:
          description: Successfully returned information about users 
          schema:
            type: array
            items:
              type: object
              properties:
                username:
                  type: "string"
                  example: "kesh92"
                created_time:
                  type: "dateTime"
                  example: "2010-01-12T05:23:19+0000"

请注意,每个响应项中都描述了数据类型以及终端用户通过成功的 GET 调用可以期望获得的示例。终端用户在 JSON 中收到的成功响应如下所示。  

{
   “data”:[
      {
         “Username”:“example_user1”,
         “created_time":“2013-12-23T05:51:14+0000         ”
      },
      {
         “username”:“example_user2”,
         “created_time":“2015-3-19T17:51:15+0000         ”
      }
….
   ]
}

如果终端用户使用 GET 方法成功调用端点,则用户应获得上述数据以及 200 响应代码,以验证是否正确使用。同样,不正确的调用应生成相应的 400 或 500 响应代码,并提供相关信息以帮助用户更好地操作集合。

请求

优雅地处理复杂性

您尝试公开的数据可以由许多属性来表征,这些属性对于使用您的 API 的终端消费者可能是有益的。这些属性描述了基本资源,并隔离了可以使用适当方法操作的特定信息资产。 API 应力求完整,并提供所有必要的信息、数据和资源,以帮助开发人员以无缝的方式集成。 但完整性意味着要考虑 API 的常见用例。可能存在许多此类关系和属性,为每个关系和属性都定义资源不是一个好做法。 还应考虑资源公开的数据量。如果您尝试公开大量数据,则可能会对服务器产生负面影响,尤其是在负载和性能方面。 以上情况和关系是 API 设计中需要考虑的重要因素,可以使用适当的参数来处理。您可以使用查询参数中的“?”来扫除属性并限制响应,或者使用路径参数来隔离客户端正在使用的特定数据组件。 让我们以我们的照片分享应用程序为例。 开发人员获取特定位置和特定主题标签中共享的所有照片的信息可能是有用的。您还希望将每次 API 调用的结果数量限制为 10 个,以防止服务器负载过高。如果终端用户想要查找波士顿所有带有主题标签 #winter 的照片,则调用将是:

GET /photos?location=boston&hashtag=winter&limit=10

请注意,复杂性现在已简化为与查询参数的简单关联。如果您想根据客户端的请求提供有关特定用户的信息,则调用将是:

GET /users/kesh92

其中 kesh92 是 users 集合中特定用户的用户名,它将返回 kesh92 的位置和加入日期。 这些只是您设计参数的一些方法,这些参数力求 API 的完整性,并帮助您的终端开发人员直观地使用您的 API。     最后,当有疑问时,就删除它。如果您对特定资源或集合的功能有疑虑,则将其保留到下一次迭代。开发和维护 API 是一个持续的过程,等待来自正确用户的反馈对于构建一个强大的 API 至关重要,该 API 使用户能够以创造性的方式集成和开发应用程序。

开始 API 设计

没有一种适用于所有组织的 API 设计方法。上述建议仅仅是 根据您的用例和要求可以采用或舍弃的建议和意见。 API 设计至关重要的主要原因之一是帮助终端用户使用您的 API。他们的需求应该是设计和构建出色 API 的指导方针。 

感谢您的阅读!正在寻找更多 API 资源?订阅 Swagger 新闻通讯。每月接收包含我们最好的 API 文章、培训、教程等内容的电子邮件。 订阅