我见过最烂的 API 设计,连 PM 都看不下去了
做后端开发这些年,看过的 API 比你看过的网络小说还多。说实话,大部分都是垃圾——不是功能实现得差,而是接口设计得让人想打人。
今天不整虚的,直接聊几个真实项目中见过的 API 设计毛病,顺便给点靠谱的改进思路。信不信由你,但这些都是血泪教训。
一、你的 URL 结构暴露了你的人品
先看几个我亲眼见过的骚操作:
GET /getUserById?id=123
POST /createNewUser
PUT /updateUserInfo
DELETE /deleteUser
看到这种 API,我内心是崩溃的。这不叫 REST,这叫"我用 HTTP 动词当装饰"。
RESTful API 的 URL 应该是名词,不是动词。动词是 HTTP 方法该干的事。正确姿势:
GET /users/123 # 获取用户
POST /users # 创建用户
PUT /users/123 # 更新用户
DELETE /users/123 # 删除用户
简单、清晰、一目了然。别人拿到这个 API 文档,不用猜就知道干嘛的。
好的 URL 结构是自我解释的,不需要注释。
二、状态码用错,比写错别字还丢人
很多人写 API 返回数据长这样:
{
"code": 200,
"message": "success",
"data": { ... }
}
然后不管出啥错都返回 200 OK。这不是误导前端吗?200 意味着"一切正常",你数据库崩了也返回 200,前端还以为一切顺利呢。
HTTP 状态码是干嘛用的?就是让调用方不用解析你的 body 就能知道请求结果。好好用:
- 200 - 成功(GET、PUT、PATCH、DELETE 操作成功)
- 201 - 资源创建成功(POST 创建了新资源)
- 400 - 请求参数有问题(前端别甩锅了,是你 API 接收格式不对)
- 401 - 没登录或 Token 过期(请重新登录)
- 403 - 登录了但没权限(你不是 VIP,不能访问这个资源)
- 404 - 资源不存在(你找的那玩意儿早没了)
- 429 - 请求太频繁(限流了,别疯狂刷)
- 500 - 服务器炸了(我们的锅,赔礼道歉中)
前端拿到 401 就知道要跳转登录页,拿到 403 就知道要提示权限不足,根本不用解析你的 body。这才叫前后端配合。
三、分页参数瞎写,数据库背锅
这种分页参数你见过吗?
GET /users?page=1&limit=20&sort=created_at&order=desc&search=关键词
看起来挺标准?问题在于 sort 和 order 这俩字段。
sort 参数直接传字段名,假设有个字段叫 user_name,前端直接传 sort=user_name。万一这是个 SQL 注入漏洞呢?或者字段名拼错了呢?
更好的做法:
GET /users?page=1&limit=20&sort_by=created_at&order=desc
后端做一个白名单校验,只允许特定的字段名参与排序。数据库字段是内部实现,不应该暴露给外部。
API 是对外的合同,合同里的字段名应该稳定、可预期、不暴露实现细节。
四、返回结构不统一,前端想骂人
看这个场景:
# 第一次请求
GET /users/123
{
"id": 123,
"name": "张三",
"email": "zhangsan@example.com"
}
# 第二次请求
GET /users
[
{"id": 123, "name": "张三", ...},
{"id": 124, "name": "李四", ...}
]
单个资源和资源列表,返回结构不一样?前端得多写多少判断代码?列表接口返回一个包装对象会死吗?
统一返回格式是基本礼仪:
{
"code": 0,
"message": "success",
"data": {
"items": [...],
"total": 100,
"page": 1,
"page_size": 20
}
}
不管查一个还是查一百个,结构都一样。前端拿到 data.items 就能直接渲染,不用先判断 data 是数组还是对象。
五、版本号乱飞,升级一次改半死
没做版本控制之前:
/api/getUserInfo
/api/queryUser
/api/fetchUserData
三年后,这三个接口分别由三个离职的同事维护,没人知道它们有什么区别。这就是技术债务,利滚利的那种。
RESTful 风格推荐在 URL 里带版本号:
/api/v1/users
/api/v2/users
v1 和 v2 可以同时跑一段时间,让前端慢慢迁移。v2 接口改了响应结构,v1 用户不受影响。平滑过渡,不伤感情。
六、缺乏文档等于没有 API
很多人写完代码就交付,文档?不存在的。调用方自己猜去吧,猜错了算你倒霉。
说真的,给你的 API 写个文档不丢人。至少包含:
- 接口描述(这个 API 干什么用)
- 请求方法和 URL
- 请求参数说明(类型、是否必填、取值范围)
- 响应结构和示例
- 错误码说明
- 调用示例(cURL、HTTP、Python 都来一个)
用 Swagger/OpenAPI 规范写,直接生成交互式文档。调用方点点鼠标就能测试,比你发一百页 Word 文档强一万倍。
写在最后
API 设计这事,说难听点,暴露了一个程序员的基本素养。是只想实现功能,还是真的在为调用方考虑?是有全局观,还是写完就跑?
好的 API 设计有这几个特点:
- 看 URL 就能猜出功能
- 看状态码就知道结果
- 看文档就能调用,不需要电话沟通
- 改实现不影响调用方(你改数据库字段,别人不用动)
下次写 API 之前,先问自己一个问题:如果别人要用我这个 API,我会觉得丢脸吗?
如果会,那就改。如果不会,那恭喜你,你是个合格的后端工程师了。
(完)