API 设计原则与最佳实践
引言
大家好,今天想聊聊 API 设计这个话题。说实话,我刚入行那会儿,对 API 设计完全没概念,觉得能跑就行。结果呢?后来维护自己写的那些“能跑”的接口时,差点没把自己坑死——命名不规范、错误码混乱、文档全靠口口相传,新人接手时一头雾水。
后来踩坑踩多了,慢慢也就总结出一些经验。今天把这些心得整理一下,分享给正在学习或者刚接触后端开发的朋友。虽说不上是什么金科玉律,但都是实战中验证过的做法,希望能帮大家少走弯路。
RESTful 风格:让 URL 说话
首先聊聊 RESTful,这东西已经被说烂了,但我还是觉得它是最值得遵守的设计原则之一。
什么叫“让 URL 说话”?意思就是光看 URL,你就能大概猜到这个接口是干什么的。比如:
GET /users/123/orders
你一看就知道,这是获取 ID 为 123 的用户的所有订单。再比如:
POST /articles
这是创建一篇文章。很简单,对吧?
但我见过不少人的 API 是这样的:
GET /getUserInfo?id=123
POST /createNewArticle
这种就属于“假装 RESTful”,其实还是老一套的命令式风格。URL 里出现了动词,看起来就不够优雅。
我的建议是,资源用名词表示,复数形式比较常见。动作交给 HTTP 方法来完成。下面这些可以当作参考:
GET /users # 获取用户列表
GET /users/123 # 获取单个用户
POST /users # 创建用户
PUT /users/123 # 完整更新用户
PATCH /users/123 # 部分更新用户
DELETE /users/123 # 删除用户
坚持用这种风格,代码的可读性和一致性都会好很多。
HTTP 方法用对了,事儿就成了一半
说完 URL,再来说说 HTTP 方法。很多人觉得 GET 和 POST 能搞定一切,干嘛搞那么复杂?这话对初学者来说没问题,但当你需要设计一个严谨的 API 时,方法的选用其实很重要。
GET 用来获取资源,不应该改变服务端状态。简单说就是“只读”。 POST 用来创建资源,有时候也可以用于一些复杂的查询操作。 PUT 是全量更新,意思是你传过来的数据会完全替换掉原来的。所以 PUT 请求通常需要包含资源的完整字段。 PATCH 是局部更新,只传需要修改的字段就好。比如用户想改个昵称,用 PATCH 就很合适:PATCH /users/123
{
"nickname": "新昵称"
}
这里有个坑很多人会踩:用 GET 方法做有副作用的操作。比如有人为了“简单”,用 GET 触发一些状态变更。这是不对的,GET 必须是幂等的,多次执行不会产生副作用。
还有个词叫“幂等”,简单解释一下:就是同一个请求执行一次和执行多次,结果是一样的。GET、PUT、DELETE 都是幂等的,POST 不是。设计 API 的时候想清楚这一点,能避免很多奇怪的 bug。
状态码别乱用,该是什么就是什么
接下来聊聊状态码。这个东西说大不大,但用好了能省很多沟通成本。
最常见的状态码:
- 200 OK:请求成功,返回数据
- 201 Created:创建资源成功,通常配合 POST 使用
- 400 Bad Request:请求参数有问题,比如缺少必填字段
- 401 Unauthorized:未认证,需要登录
- 403 Forbidden:没有权限访问这个资源
- 404 Not Found:资源不存在
- 500 Internal Server Error:服务器内部错误
我见过不少人,所有错误都返回 200,然后在 body 里写个 {"code": 500, "message": "error"}。这种做法不能说错,但确实不够规范。前端开发者在处理这种响应的时候,往往需要多写一堆判断逻辑。
我的建议是,能用 HTTP 状态码表达的意思,就尽量用状态码。错误信息放在响应 body 里详细说明,这样职责分离,清晰明了。
// 400 错误示例
{
"error": "VALIDATION_ERROR",
"message": "邮箱格式不正确",
"details": [
{
"field": "email",
"message": "请输入有效的邮箱地址"
}
]
}
这种结构就很好,前端可以根据 error 字段做国际化处理,根据 details 展示具体哪个字段有问题。
版本化:给 API 留条后路
API 版本化是个大问题,很多人一开始觉得不需要,等真的需要改接口结构的时候,就傻眼了。
常见的版本化方式有几种:
URL 路径版本化(最常见):/api/v1/users
/api/v2/users
Accept: application/vnd.myapp.v2+json
/users?version=2
我个人比较推荐 URL 路径版本化,原因很简单——直观。开发和调试的时候,一眼就能看出调用的是哪个版本。
版本化最核心的原则是:旧版本要尽量保持兼容,给客户端足够的迁移时间。不能一声不响就把 v1 停了,那样会害死人。
一般来说,新版本上线后,旧版本至少要保留一到两个版本。等所有客户端都迁移得差不多了,再考虑下线的事儿。
文档和错误处理:好 UX 的关键
最后聊聊文档和错误处理,这两个东西做好了,使用你 API 的人会感谢你的。
先说文档。现在有很多工具可以自动生成 API 文档,比如 Swagger/OpenAPI、Apifox 这些。强烈建议大家用起来,别再写那种 Word 文档了,既不好维护,调试也不方便。
一份好的 API 文档应该包含:
- 每个接口的用途说明
- 请求参数列表(名称、类型、是否必填、示例值)
- 响应结构(成功和失败的都要有)
- 错误码说明
- 认证方式
再说错误处理。除了前面提到的状态码,错误信息也要写得友好。别返回“System error”这种鬼话,用户看到根本不知道发生了什么。
// 不好的错误
{
"error": "error",
"message": "操作失败"
}
// 好的错误
{
"error": "INSUFFICIENT_BALANCE",
"message": "余额不足,请充值后再试",
"code": 1002
}
错误信息要告诉使用者:发生了什么问题、可能的原因、以及建议的下一步操作。这样的 API 用起来才舒服。
总结
好啦,今天聊了 API 设计的几个关键点:RESTful 风格、HTTP 方法的正确使用、状态码的规范、版本化管理、以及文档和错误处理。
这些原则看起来简单,但真正坚持下来并不容易。我自己也经常会在赶进度的时候偷懒,写出一些不那么规范的接口。但长期来看,规范的 API 设计能省下大量维护成本,团队协作也会顺畅很多。
如果你正在学习后端开发,或者刚接手一个 API 项目,不妨从这些小点开始改进。一开始不需要追求完美,慢慢迭代就好。
希望这篇文章对你有帮助。如果有什麼问题或者不同的看法,欢迎在评论区聊聊。我们下期再见!
API 设计原则与最佳实践
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法