## 当RESTful成为教条
工作了这么多年,我见过太多这样的场景:
"这个接口应该用GET还是POST?"
"当然是GET啊,RESTful规范说的!"
"可是我要传一个很复杂的查询条件..."
"那就用POST!不行就整个/search接口!"
每次听到这种对话,我就知道又有人把RESTful玩成了宗教信仰。
## RESTful的真相:它只是一个约定,不是法律
让我说句大实话:Roy Fielding发明REST的时候,可没想过你们会把所有接口都套进那几条规则里。他老人家要是看到你们为了一个查询参数要不要放path里吵半天,估计会笑出声。
RESTful的核心思想是"表现层状态转移",重点是"状态"和"资源"。但现实是,大部分业务场景根本没那么复杂,你们只是在:无中生有地"资源化"每一个概念。
比如有个需求:"用户登录成功后,需要获取用户的详细信息"
按照某些人的理解,必须搞成:
```
GET /users/{userId}
```
然后前端先调用登录接口拿到token,再调这个接口。好家伙,一个简单需求硬拆成两个接口,美其名曰"符合RESTful规范"。
为什么就不能有一个:
```
POST /auth/login-with-profile
```
一次请求解决所有问题,用户体验直接起飞。
## 真正值钱的API设计原则
### 1. 业务导向,而不是技术导向
好的API应该是这样的:
- 这个接口解决什么业务问题?
- 调用方需要什么数据?
- 怎么样让调用方写得最少?
而不是:
- 这个操作符不符合HTTP语义?
- 这个路径够不够RESTful?
我见过最离谱的案例:一个"修改密码"功能被拆成了:
```
GET /passwords/{userId} # 先获取当前密码信息
PUT /passwords/{userId} # 再更新密码
```
wtf?修改密码不应该就是一个POST或者PUT的事情吗?
### 2. 批量操作是刚需,别假装不存在
总是有人信誓旦旦地说:"批量操作不符合RESTful最佳实践"
去他大爷的最佳实践。
```json
POST /users/batch-delete
{
"ids": [1, 2, 3, 100, 500]
}
```
vs
```
DELETE /users/1
DELETE /users/2
DELETE /users/3
DELETE /users/100
DELETE /users/500
```
前者一次网络请求,后者五次。用户体验不在一个维度。这不是最佳实践什么是?
### 3. 版本控制要务实
URL版本:
```
/api/v1/users
/api/v2/users
```
Header版本:
```
Accept: application/vnd.myapp.v2+json
```
我的建议:除非你的API要对外开放给第三方,否则URL版本就够了。简单、直观、便于调试。
### 4. 错误信息要有诚意
很多API的错误返回是这样的:
```json
{
"error": "Invalid request",
"code": 400
}
```
这等于什么都没说。好的错误返回应该是:
```json
{
"error": "validation_failed",
"message": "创建订单失败:商品库存不足(商品ID: 12345,当前库存: 0)",
"details": {
"field": "items[0].quantity",
"reason": "stock_insufficient"
},
"request_id": "req_abc123"
}
```
前端看到这种错误,想不知道问题在哪都难。
## GraphQL不是银弹,RPC也不是
近几年GraphQL火得不行,很多人开始跟风:"我们要用GraphQL!"
兄弟,GraphQL确实解决了"Over-fetching"和"Under-fetching"的问题,但它带来了:
- 查询复杂度难以控制(一个烂Query能把你数据库查挂)
- 缓存策略变得复杂
- 学习成本增加
同样的,RPC风格也不是万能的。它适合内部服务间的高性能通信,但不是给前端调用的最佳选择。
我的态度是:根据场景选技术,而不是根据潮流选技术。
## 实践建议
### 给后端工程师
1. **多和前端聊聊**:了解他们真正需要什么,而不是你觉得他们需要什么
2. **减少请求次数**:能一次返回的数据,不要让前端调两次
3. **做好接口文档**:好的文档能减少一半的沟通成本
4. **保持接口稳定**:既然发布了就别随便改,改了要通知到位
### 给前端工程师
1. **别惯着后端**:不合理的接口该喷就要喷
2. **学会提需求**:"我需要一个能一次性获取这些信息的接口"比"你给我加个字段"强一百倍
3. **做好错误处理**:接口不可能永远成功,错误处理要做好
## 写在最后
API设计本质上是一门"为人服务"的艺术。技术规范是工具,不是目的。
别再为了"符合规范"而牺牲用户体验了。你的接口是给人用的,不是给评审专家看的。
最后送大家一句话:**好的API用起来,就像呼吸一样自然。**
共勉。