做后端开发这些年,我见过太多API设计得让人想砸键盘。不是接口慢得像爬虫,就是返回结构乱得让人怀疑人生。今天把这10年踩过的坑整理一下,希望你们别再重蹈覆辙。
1. 命名:让人看懂比显得自己牛更重要
见过最离谱的接口名:getNttInfoByCond。ntt是什么?condition又是什么?猜去吧。
好的命名应该是自解释的:
// 烂名字
getNttInfoByCond
fuzzyQueryUser
updateRec
// 好名字
getNotificationByCondition // 虽然还是模糊,但至少能猜
searchUsers // 清晰
updateRecommendation // 全拼,不猜
// 最佳实践
getUserNotifications // 名词复数,资源导向
searchArticlesByTag // 动作+资源+过滤条件
记住:代码是写给人看的,API是给其他开发者用的。让他们少猜一次,你就少挨骂一次。
2. HTTP方法:用对了吗?
这个问题在团队里能吵三天。
// 很多人这么干
POST /api/updateUser // 更新用POST?
POST /api/deleteUser?id=123 // 删除也用POST?
GET /api/saveArticle // 保存用GET??
// 标准做法
PUT /api/users/123 // 更新用户
DELETE /api/users/123 // 删除用户
POST /api/articles // 创建文章
GET /api/articles // 查询文章列表
几个原则:
- GET:只读,不修改任何东西
- POST:创建资源
- PUT:完整更新(替换)
- PATCH:部分更新
- DELETE:删除
如果你的接口不遵循这些,其他开发者接的时候心里一定是骂娘的。
3. 状态码:别总是200 OK
有些接口永远返回200,但code字段是1表示失败。这是初级的做法,但不是好做法。
// 糟糕:HTTP 200 + 业务code
{
"code": 1,
"message": "用户不存在",
"data": null
}
// 好做法:正确的HTTP状态码
HTTP 404 Not Found
{
"error": "user_not_found",
"message": "用户不存在"
}
// 认证失败
HTTP 401 Unauthorized
{
"error": "invalid_token",
"message": "Token已过期"
}
// 参数错误
HTTP 400 Bad Request
{
"error": "validation_failed",
"message": "手机号格式不正确",
"fields": ["phone"]
}
标准HTTP状态码是语言,用对了事半功倍。
4. 分页:Page还是Offset?
这是另一个能引发团队血案的话题。
// OFFSET方式(简单但有性能问题)
GET /api/users?page=1&page_size=20
// Cursor方式(性能好,但只支持单向)
GET /api/users?cursor=xxx&limit=20
// 时间范围方式(适合日志类数据)
GET /api/orders?start_time=2025-01-01&end_time=2025-01-31
数据量小用Page,数据量大用Cursor。简单粗暴但有效。
5. 版本管理:早做比晚做好
没做版本管理的API,最后都会变成噩梦。
// 路径版本(最常见)
/api/v1/users
/api/v2/users
// Header方式
API-Version: 2024-01-01
// Query参数(不推荐)
/api/users?version=2
路径版本最直观,但要注意:v1维护成本不低,能不维护就不维护,推动上游尽快升级才是正道。
6. 错误信息:给开发者看的,不是给用户看的
错误信息要写给接手你接口的开发者看,不是给终端用户看。
// 烂错误信息
{"error": "操作失败"}
{"error": "参数错误"}
// 好的错误信息
{
"error": "validation_error",
"message": "请求参数验证失败",
"details": {
"field": "email",
"reason": "邮箱格式不正确",
"received_value": "abc"
}
}
// 更进一步:给出文档链接
{
"error": "resource_not_found",
"message": "文章不存在",
"documentation_url": "https://api.example.com/docs/errors#article-not-found"
}
7. 性能:N+1是每个后端人的噩梦
最常见的性能杀手:
// 典型N+1
GET /api/users/123
// 返回
{
"name": "张三",
"posts": [
{ "id": 1, "title": "文章1", "author_id": 456 }, // 456是谁?
{ "id": 2, "title": "文章2", "author_id": 789 } // 789又是谁?
]
}
// 解决方案1:嵌套返回
GET /api/users/123?include=posts.author
// 解决方案2:分开调用,但用缓存
// 第一次调用后,author信息被缓存,后续调用不查库
原则:一次能查完的,不要分多次。除非你打算以后做微服务拆分。
8. 安全:基础中的基础
// CORS配置(开发环境图方便,生产环境要严谨)
// 烂:
Access-Control-Allow-Origin: *
// 好:
Access-Control-Allow-Origin: https://yourdomain.com
// 速率限制(保护你的服务)
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640000000
// 敏感操作要审计
POST /api/orders (应该记录操作日志)
POST /api/refunds (更应该记录)
总结
API设计没有绝对的标准,但有几个通用原则:
- 命名即文档:名字起好,注释少一半
- 遵循HTTP语义:方法对、状态码对
- 错误信息要有用:让调用者知道错在哪
- 性能要考虑:N+1是万恶之源
- 安全是底线:别等到被刷才想起来加限制
好的API设计不会让你出名,但会让你的同事少骂你。祝各位的接口都稳稳当当,调用者都心平气和。