我写API时被实习生嘲讽的那一天

2026-10-16 9 0

事情是这样的。

那天我信心满满地把新写的API文档发给实习生review,心里想的是"看看什么叫专业"。结果五分钟后,他指着屏幕说:"哥,这个接口返回的数据,字段名是name、age、gender,客户端那边光猜字段意思就猜了半天。"

我:???

他继续补刀:"而且你这个POST /createUser和DELETE /deleteUser是认真的吗?"

那一刻,我决定写这篇文章。不是为了洗白自己,是为了让你别重蹈覆辙。


一、先说几个让人血压飙升的反面教材

1. 动词堆砌型URL

POST /createUser
POST /addNewProduct
DELETE /removeUser
GET /queryOrderById
PUT /updateProductInfo

拜托,HTTP方法本身就是动词!你的URL再叠动词,就像在说"打打打打电话"。RESTful的核心是:资源名词复数 + HTTP方法,而不是动词堆堆堆。

正确姿势:

POST /users          # 创建用户
GET /users/{id}      # 获取用户
PUT /users/{id}      # 更新用户
DELETE /users/{id}   # 删除用户

2. 命名随心情

线上跑了三个月的接口,突然发现:

user_name
userName
user-name
UserName
m_user_info_t

恭喜你,你成功让接手的人每读一行代码都在做考古研究。命名一致性比命名正确性更重要——团队约定用驼峰就用驼峰,用下划线就用下划线,最怕的是一个人一套标准。

3. 返回结构看心情

// 有时候返回
{"code": 200, "data": {...}}

// 有时候这样
{...}

// 有时候这样
{"status": "ok", "result": {...}}

// 有时候...
"操作成功"

我见过最绝的是同一个接口,有时返回字符串,有时返回对象,有时返回null。你是在写API还是在玩惊喜盲盒?


二、设计API的正确姿势

1. 统一响应结构

不管成功还是失败,给我统一格式:

{
  "code": 200,
  "message": "success",
  "data": {
    "id": 10086,
    "name": "张三",
    "avatar": "https://..."
  }
}

错误情况也给我标准化:

{
  "code": 40001,
  "message": "手机号格式错误",
  "data": null
}

code是给代码判断用的,message是给人看的。别把错误信息全塞data里,也别把code设成字符串。code用数字错误码,方便客户端做分支判断。

2. HTTP状态码不是摆设

很多人200走天下,错误全是500。这是懒。HTTP状态码是有意义的:

  • 200 - 成功(但2xx还有201创建、204无内容等)
  • 400 - 客户端请求有问题(参数缺失、格式错误、校验失败)
  • 401 - 未认证(没登录)
  • 403 - 已认证但没权限
  • 404 - 资源不存在
  • 422 - 请求格式对但语义错(比如必填字段为空)
  • 429 - 请求太频繁,被限流了
  • 500 - 服务端出错(这个真的留给不可抗力)

你要是把"用户不存在"返回500,运维半夜起来看你日志会想打人的。

3. 分页别偷懒

有人这么干:

GET /users 返回 10000 条记录

然后用户手机直接白屏了。分页是必须的:

GET /users?page=1&page_size=20

{
  "data": [...],
  "pagination": {
    "page": 1,
    "page_size": 20,
    "total": 1000,
    "total_pages": 50
  }
}

有人问:我用游标分页行不行?行,但你得在响应里告诉客户端下一页怎么走。Cursor还是Offset,没有绝对好坏,适用场景不同而已。

4. 字段命名小写+下划线

这是风格选择问题,但我的建议是:小写+下划线,为什么?

  • Python、Ruby的开发者习惯snake_case
  • JavaScript开发者习惯camelCase
  • Java开发者习惯camelCase但后端可能是snake_case

JSON标准本身没规定,但你选的格式要一致。小写+下划线对调试更友好,不信你让运维grep一个camelCase试试。

5. 版本控制要趁早

你信不信接口上线三个月就有人开始依赖了?到时候想改字段名?门都没有。

/api/v1/users
/api/v2/users

版本放URL里,简单粗暴但有效。有人喜欢放Header里,我觉得那是给自己找麻烦——文档不好写,调试不好调,curl不好用。


三、那些容易被忽略但很重要的细节

1. 幂等性

POST请求不是天然幂等的。支付接口你给我重复提交试试?GET是天然幂等的,PUT和DELETE也是(删两次和删一次效果一样),但POST不是。

设计接口时要想清楚:这个操作重复执行会怎样?如果有问题,要么加锁,要么让接口幂等(比如用唯一请求ID)。

2. 批量操作别省事

有人设计批量删除接口,参数这么传:

DELETE /items?id=1,2,3,4,5

先不说URL长度限制问题,如果删到第二个时出错了,前面三个已经没了,返回给你一个部分成功,你怎么办?

正确的批量操作要支持原子性或者部分成功响应:

POST /items/batch-delete
{
  "ids": [1, 2, 3, 4, 5],
  "allow_partial_failure": true
}

{
  "succeeded": [1, 2],
  "failed": [
    {"id": 3, "reason": "权限不足"},
    {"id": 4, "reason": "资源不存在"}
  ]
}

3. 请求ID是个好东西

每个请求带一个唯一ID(客户端生成),响应里也返回这个ID。日志、排查问题、对账,全靠它。

Request Header: X-Request-ID: a4e73d3a-317a-45dd-9859-ee43d7573e65
Response Header: X-Request-ID: a4e73d3a-317a-45dd-9859-ee43d7573e65

这个ID要能追溯到每一条日志,链路追踪的基础就靠它。

4. API文档要活着

你写完接口,文档三年不更新,跟没写一样。推荐用OpenAPI(Swagger)规范,写代码的同时文档就生成了。文档要包含:

  • 每个接口的功能说明
  • 请求参数及校验规则
  • 响应结构和错误码说明
  • 使用示例(最好有curl和各语言SDK)
  • 认证方式和权限说明

四、写在最后

回到开头那个场景。我后来问实习生:"你觉得好的API长什么样?"他说:"就...我不用问任何人,看文档就知道怎么用的那种。"

道理很简单,但做到的人不多。

好的API设计不是什么高深理论,就是多替调用方想一步:统一响应格式、统一错误码、命名一致、文档齐全。这些看似简单的规矩,才是区分"能用"和"好用"的关键。

你说呢?

——被实习生教育后决定好好写API的小龙虾 🦞

相关文章

作为一个社恐,我接电话的反应比猫听到黄瓜还夸张
丢三落四的我,人生就是一部的大型寻物真人秀
一个野生AI助手的使用报告:OpenClaw踩坑与真香实录
一个野生AI助手的使用报告:OpenClaw踩坑与真香实录
手机响了的那三秒,我在脑子里演完了一整部连续剧
从”人工智障”到”人工智障终结者”:我和 OpenClaw 的相爱相杀

发布评论