本文发表于 679 天前,其中的信息可能已经事过境迁

开发不挨骂指南为本博客系列文章,将会不定期更新。

文章开始前,我先认个罪,在早期AI摘要开发中,由于当时刚入门后端,没有任何规范性可言,所以导致后期维护成本极高,也给协作开发带来了很多困难。所以,我希望通过我自己的经验,给大家分享一些规范化API设计的经验,防止像我一样,后期拓展困难,重构困难,团队协作困难。

在此之前,作为读者,你需要了解一些基本的网络知识,比如HTTP协议,同时你需要确保自己有一定的独立思考的能力,因为风格选取是一个很主观的事情,不同的人有不同的看法,但是规范化设计是必须的。

背景

现目前,前后端分离开发已经成为主流,前端通过调用后端提供的API接口来获取数据,而后端则需要提供一套规范化的API接口,在云服务大行其道的今天,API接口的规范化设计显得尤为重要,无论你是否是专业开发者,就比如你想写一个简单的数据获取接口,你也希望拿到的数据是规范化的,而不是一团乱麻。

好的产品设计,不仅仅是产品本身,还有产品的接口设计,接口规范将有助于团队协作,对产品来说,好的规范也有助于前端展开和用户的交互逻辑。而一个设计不合理的接口将会可能导致来自团队成员或者同事的“爱意”。就我个人而言,今天肯定会给以前的自己竖中指,写的什么屎山玩意儿,导致我今天想重构很多地方都得花很多时间。

同时,现在市面上也有很多规范标准,其中主要分为两大思想,一种是ROA思想,一种是RPC思想,下面我们将分别介绍。

以下没有详细展开,这里仅做展示,并不严谨,您可参考我给出的链接文档详细了解。

ROA思想

ROA思想推荐参考此文档:RESTful API 最佳实践

ROA(Resource-Oriented Architecture)是一种面向资源的架构风格,它是一种基于资源的设计风格,它的核心思想是将资源作为核心概念,通过资源的标识符来对资源进行操作,资源的标识符通常是一个URL,通过HTTP协议来对资源进行操作。

ROA思想比较出名的就是RESTful风格,RESTful是一种基于HTTP协议的API设计风格,它的核心思想是将资源作为核心概念,通过资源的标识符来对资源进行操作,资源的标识符通常是一个URL,通过HTTP协议来对资源进行操作。

RESTful风格的API设计有一些基本原则:

  • 使用HTTP方法来对资源进行操作,GET用于获取资源,POST用于创建资源,PUT用于更新资源,DELETE用于删除资源。

  • 使用URL来标识资源,URL中不应该包含动词,只包含名词,资源的操作通过HTTP方法来实现。

  • 使用HTTP状态码来表示操作结果,2xx表示成功,4xx表示客户端错误,5xx表示服务端错误。

就看上面的这些原则未免过于抽象,下面我们通过一个简单的例子来说明RESTful风格的API设计。假设我们现在有一个商品管理系统,我们需要针对其中的商品进行增删改查操作,我们可以设计如下的API

添加商品:

HTTP
POST /products

{
    "name": "iPhone 114514",
    "price": 6999
}

Response:
{
    "id": 1,
    "name": "iPhone 114514",
    "price": 6999
}

获取商品:

HTTP
GET /products/1

Response:
{
    "id": 1,
    "name": "iPhone 114514",
    "price": 6999
}

更新商品信息:

HTTP

PUT /products/1

{
    "name": "iPhone 114514",
    "price": 7999
}

Response:
{
    "id": 1,
    "name": "iPhone 114514",
    "price": 7999
}

删除商品:

HTTP

DELETE /products/1

Response:
{
    "message": "success"
}

以上的例子中,你可以发现我们使用了HTTP方法来对资源进行操作,使用URL来标识资源,使用HTTP状态码来表示操作结果,这就是RESTful风格的API设计,看起来似乎RESTful风格的API设计是一种非常好的设计风格,但是实际上RESTful风格的API设计并不适用于所有的场景,很多常见的操作根本无法通过HTTP方法来实现,比如说登录操作,你应该使用哪种HTTP方法来实现登录操作呢?(在实际应用中,很多操作依靠POST进行实现)这就是RESTful风格的API设计的一个缺点,它并不适用于所有的场景。

这里并没有踩一捧一的意思,实际上,不仅在我,很多人都对RESTful风格的API设计有很多的争议,这里只是提供一种设计思路,具体的设计风格还需要根据实际情况来确定。

RPC思想

RPC思想推荐参考此文档:RPC框架:从原理到选型,一文带你搞懂RPC

RPC(Remote Procedure Call)是一种远程过程调用的协议,它的核心思想是通过远程调用的方式来调用远程服务,RPC的核心思想是将服务作为核心概念,通过服务的标识符来对服务进行操作,服务的标识符通常是一个字符串,通过RPC协议来对服务进行操作。

  • 过程调用:客户端调用远程服务器上的过程就像调用本地函数一样,通常通过函数名和参数列表来定义。

  • 语言无关:RPC可以跨语言工作,只要双方遵循相同的接口定义。

  • 性能优化:由于RPC框架通常采用二进制序列化和优化过的传输协议,因此在性能上可能优于基于文本的协议(如JSON over HTTP)。

同样的,以下是RPC思想的一个简单例子:

创建商品:

HTTP
POST /product-service/create-product

{
    "name": "iPhone 114514",
    "price": 6999
}

Response:
{
    "id": 1,
    "name": "iPhone 114514",
    "price": 6999
}

获取商品:

HTTP
POST /product-service/get-product

{
    "id": 1
}

Response:
{
    "id": 1,
    "name": "iPhone 114514",
    "price": 6999
}

更新商品:

HTTP

POST /product-service/update-product

{
    "id": 1,
    "name": "iPhone 114514 Pro Max",
    "price": 8999
}

Response:
{
    "id": 1,
    "name": "iPhone 114514 Pro Max",
    "price": 8999
}

删除商品:

HTTP

POST /product-service/delete-product

{
    "id": 1
}

Response:
{
    "message": "Product with ID 1 has been deleted."
}

以上的例子中,你可以发现我们使用了POST方法来对资源进行操作,使用URL来标识资源,使用HTTP状态码来表示操作结果,这就是RPC风格的API设计,RPC风格的API设计更加注重远程过程调用,而不是资源的表述,这样的设计虽然不是严格意义上的RESTful,但在某些情况下,它可以提供更加灵活的API设计,并且更容易映射到后端的服务实现。

RPC风格不像ROA风格那样有着严格的规范,它更加灵活,可以根据实际情况来设计API

思考

在以上两种思想中,仅展示了两种设计风格差异,实际上都不是比较严谨,不过,不论你选择哪种设计风格,都需要遵循一些基本的设计原则,比如说:

  • 设计思路明确,不要纠结该使用POST还是GET

  • 较为复杂的系统不要过于依赖HTTP状态码,最好在返回结果中包含错误码和错误信息,提前约定好错误码和错误信息,也有利于后续开发拓展。

  • 保持风格一致性,无论选择成熟规范还是自定义规范,都要保持风格一致性,在整个API中保持一致的命名约定和行为模式。这包括但不限于资源的命名、HTTP方法的使用、错误响应格式等。一致性可以降低学习成本,使API更易于理解和使用。

  • 可读性和可预测性,API设计应该尽量简单明了,让用户能够快速理解和使用。API的行为应该是可预测的,用户可以根据API的设计来推断API的行为。

  • API简洁,API设计应该尽量简洁,比如前端一个页面需要展示多个商品,那么你可以设计一个获取多个商品的API,而不是设计一个列表API和一个获取商品详情API。

  • 文档规范,API设计应该有规范的文档,文档应该包括API的使用方法、参数说明、返回结果说明、错误码说明等。文档应该是实时更新的,保持与API的一致性。

现在有了这些指导思想,还是以上的例子,我们可以对其进行一些改进,比如说我们可以将数据信息返回的格式进行统一,比如说:

返回格式:

JSON
{
    "code": 10000, // 规范化的状态码 10000表示成功,其他表示失败,可拓展,比如10001表示参数错误,10002表示权限不足等
    "message": "success", // 状态信息 不仅可以让请求API的人更好的理解,也可以让后端开发人员更好的定位问题,也可以用于前端展示,让用户直观了解当前操作的结果
    "data": { // 数据正文信息
        "id": 1,
        "name": "iPhone 114514",
        "price": 6999
    }
}

现在,想必你已经对API设计有了一定的了解,读完这篇文章(包含两个引用链接),你一定有了自己的想法,那么,你会选择哪种设计风格呢?或者你有更好的设计风格呢?欢迎在评论区留言,让我们一起讨论。

评论 隐私政策