现在,任何网站或应用程序都可以通过 API 访问其核心功能。然而,归根结底,API 的采用取决于它的设计程度。在这篇博客中,我们将探讨 API 设计的基础知识以及您需要遵循的最佳实践,以确保开发人员喜欢您的 API。
什么是 API 设计
API 设计是定义应用程序可用于请求和交换信息的方法和数据格式的过程。它涉及指定开发人员可以使用的终结点或 URL、应发送和接收的数据格式以及 API 的预期行为。
虽然这些是 API 的技术方面,但 API 设计是由 API 的目的决定的;背后的原因。了解 API 的用途可以解决开发过程的问题,因为它提供了对预期行为、限制和潜在未来发展的见解。API 设计现在被纳入更广泛的 API 管理范围,以确保计划设计和实现的 API 之间的一致性。
如何设计 API
每个 API 都不同,具体取决于其用途和实现的功能。但是,每个开发人员都应该遵循某些通用的指导原则来构建健壮且对开发人员友好的 API。以下是你如何去做:
第 1 步:了解 API 的用途
在概述 API 的蓝图之前,请确保所有利益相关者都清楚 API 将做什么。与企业领导者密切合作,明确总体目标和目标。了解 API 将如何适应更大的图景。如果可能,请直接与将与 API 交互的最终用户或开发人员进行通信。收集有关他们的需求、痛点和期望的反馈,以深入了解 API 的实际用例。
API 的用途将决定其功能、特性、记录方式、需要哪些安全实现以及您将选择哪种 API 规范。
选择正确的 API 规范
有各种 API 规范,每种规范都适用于特定的用例。以下是一些最受欢迎的:
OpenAPI(Swagger)
OpenAPI 是用于描述 RESTful API 的广泛采用的标准。它以其简单性而闻名,因为它允许轻松生成文档,并为开发人员提供一种标准化的方式来理解 API 并与之交互。OpenAPI 使用 JSON 或 YAML 格式来指定 API 的端点、请求和响应格式以及身份验证方法。它适用于通过 HTTP 进行的无状态通信,并且是面向广泛受众的 API 的不错选择。
GraphQL 架构
GraphQL 是 RESTful API 的替代品,其规范通常使用模式语言定义。GraphQL 模式概述了可以查询的特定数据类型以及这些查询的结构。它适用于客户端需要精确控制要检索的数据的场景。
RAML(RESTful API 建模语言)
RAML 是一种基于 YAML 的语言,用于描述 RESTful API。它提供了一种人类可读的方式来定义 API 的结构、端点和数据类型。当您的首要任务是可读性和简单性时,请使用它。
SOAP(简单对象访问协议)
OAP 是一种用于在 Web 服务中交换结构化信息的协议。它通常用于需要标准化通信的企业级应用程序。当您处理旧环境时,它是最佳选择。
WSDL(Web 服务描述语言)
WSDL 通常用于描述 SOAP(简单对象访问协议)Web 服务。它定义了 Web 服务的操作、消息和数据类型,允许不同系统之间的标准化通信。它最适合需要严格合同和标准化通信的企业级应用程序。
异步API
它类似于 OpenAPI,但专为异步 API 设计,AsyncAPI 专注于消息驱动的架构,并描述如何在不同组件之间交换消息。当不需要 API 的实时响应时,会使用它。
步骤 2:定义终结点和资源
下一步是定义终结点和资源。端点定义开发人员可用于与 API 交互的特定 URL(统一资源定位符)或 URI(统一资源标识符)。每个终结点通常对应于一个特定的操作或操作。常见的 HTTP 方法(如 GET、POST、PUT 和 DELETE)用于在这些端点上执行操作。下面是一个示例:
- GET /users:检索用户列表。
- GET /users/{id}:使用用户 ID 检索特定用户的详细信息。
- POST /users:创建新用户。
- PUT /users/{id}:更新特定用户的详细信息。
- DELETE /users/{id}:删除特定用户。
资源表示 API 管理的实体或对象。这些可以是任何内容,从用户和产品到评论或系统中的任何其他相关实体。每个资源通常都有一个唯一标识符,并与一个或多个终结点相关联。例如:
资源:用户
属性:ID、用户名、电子邮件等。
端点:
/users (GET - 列出所有用户,POST - 创建一个新用户),
/users/{id}(GET - 获取用户详细信息,PUT - 更新用户详细信息,DELETE - 删除用户)
资源:产品
属性:ID、名称、描述、价格等。
端点:
/products (GET - 列出所有产品,POST - 创建新产品),
/products/{id} (GET - 检索产品详细信息,PUT - 更新产品详细信息,DELETE - 删除产品)
步骤 3:确定命名约定
如果你想让开发人员喜欢你的 API,那么请确保使用清晰一致的命名约定。在为终结点、资源和参数选择名称时不要有创意,要优先考虑清晰度和简单性。以下是一些可以帮助您的指南:
- 使用名词表示资源:
- 为您的资源选择清晰且描述性的名词。例如,/users、/products、/orders。
- 避免使用模棱两可或笼统的术语。具体传达资源的目的。
- 使用动词表示动作:
- 使用 HTTP 方法(GET、POST、PUT、DELETE)表示对资源的操作。
- 在终结点之间保持谓词的一致性。例如,使用 GET 检索用户,使用 POST 创建新用户。
- 与复数一致:
- 确定资源名称是单数还是复数,并在整个 API 中保持一致。例如,坚持使用 /user 或 /users。
步骤 3:优化请求和响应负载
设计 API 协定的另一个关键方面是指定请求和响应有效负载,这是指请求中发送的数据和响应中预期的数据。您需要做的第一件事是为 API 选择标准数据格式,例如 JSON 或 XML。最好选择 JSON,因为它因其简单性和可读性而被广泛使用。
请记住保持有效负载的轻量级,因为它们会直接影响 API 的效率。您可以采取以下措施:
1. 尝试实现有效负载压缩(例如 gzip),以减小传输过程中请求的大小。
2. 如果适用,支持可以将多个操作分组到单个请求中的批处理请求。
3. 使用查询或标头参数将 API 端点设计为仅返回客户端所需的数据。
步骤 4:实施身份验证和授权
请确保在 API 设计中考虑安全性。有两种方法可以做到这一点:身份验证和授权。
就身份验证而言,您可以实现 OAuth 和 API 密钥。API 密钥是一种简单且常用的方法,其中请求标头中包含唯一密钥。但是,这种身份验证类型不够安全。
另一方面,OAuth 是一个更健壮、更灵活的框架,适用于第三方应用程序需要访问的场景。至于授权,请明确定义用户或应用程序可以拥有的访问级别和范围。
第 5 步:使用 API 版本控制
用户需求和技术通常会随着时间的推移而变化,因此 API 必须不断发展。API 版本控制允许您在不破坏现有系统的情况下对 API 进行更改。您可以实现各种类型的 API 版本控制,例如 URL 版本控制、查询参数版本控制、标头版本控制等。
例如
URL 版本控制:https://example-api.com/v1/resource
查询参数版本控制:https://example-api.com/resource?version=v1。
步骤 6:定义相应的错误消息
在 API 使用期间,必然会发生错误。但是,重要的是如何处理这些错误。在响应正文中包含清晰简洁的错误消息,以帮助开发人员了解出了什么问题。
包括错误代码、说明和解决建议等信息。使用标准 HTTP 状态代码来指示请求的成功或失败(例如,200 OK 表示成功,404 Not Found 表示未找到资源,500 Internal Server Error 表示服务器问题)。
第 7 步:考虑意外行为
您还应该确保您的 API 可以处理来自最终用户的任何意外行为和请求。例如,最终用户最终可能会向同一资源发送多个请求,从而导致并发问题。
另一方面,您这边也可能存在问题,例如超时和响应缓慢,或者服务器最终可能会以客户端不需要的格式给出响应。您的 API 应该能够以优雅的方式处理意外操作,并显示相应的错误消息。
第 8 步:文档
现在您已经完成了所有操作,最后一部分是文档。文档就像一本手册,告诉其他开发人员你的 API 是如何工作的。它是影响 API 采用和使用的关键因素之一。因此,请确保您的文档清晰、简洁且易于理解。以下是您可以遵循的一些最佳实践:
- 避免使用不必要的技术术语,以免使开发人员感到困惑。
- 以逻辑和分层结构组织文档。使用章节、子章节和标题来帮助用户快速找到他们需要的信息。
- 包括交互式示例或 API 沙盒,以允许开发人员直接从文档中试验 API。
- 考虑使用 Swagger 或 OpenAPI 等工具生成交互式 API 文档。
API 设计优先与代码优先
在构建 API 时,您可以遵循两种方法:API 设计优先或代码优先。
我们刚才讨论的策略是 API 设计优先方法,它涉及在编写实现这些规范的实际代码之前定义 API 的规范,包括其端点、数据格式、身份验证机制和整体架构。目标是建立一个清晰且经过深思熟虑的 API 设计,以满足系统的要求,并且易于开发人员理解和使用。
另一方面,API 代码优先侧重于首先编写代码,而不定义其规范或文档。因此,开发人员会根据他们的实现经验和测试的任何反馈来调整 API,并且设计会随着代码的编写而发展。
一种方法比另一种更好吗?
可以说,API 代码优先方法提供了开发灵活性和速度,因为它允许快速原型设计。然而,也涉及很多挑战。如果没有预先明确定义的规范,则 API 的不同部分的实