2. RESTful API 设计原则:资源命名规范、HTTP方法使用、状态码选择、版本控制策略
好,咱们直接进入正题。RESTful API 设计,说白了就是一套约定。大家按规矩办事,系统才能不乱。我在量化系统里摸爬滚打这么多年,见过太多因为 API 设计不规范导致的惨案。今天我把核心原则掰开揉碎了讲给你听。
2.1 资源命名规范:你的 URL 就是你的脸面
资源命名,是 API 设计的第一步。我个人的习惯是:用名词,不用动词;用复数,不用单数;用小写,不用大写;用连字符,不用下划线。
为什么会这样?你想想看,REST 的核心是「资源」。因子、策略、回测结果,这些都是资源。操作资源的方法(增删改查)应该交给 HTTP 方法去表达,而不是塞进 URL 里。
核心原则:
- 使用名词复数:
/factors而不是/factor或/getFactor - 层级关系用斜杠:
/factors/{factor_id}/metrics - 查询参数用于过滤:
/factors?status=active&page=1 - 连字符分隔多单词:
/factor-definitions而不是/factorDefinitions
我在项目中遇到过有人把 URL 写成 /getFactorDataByDate 的。嗯,这其实是个典型的反模式。你想想,如果每个接口都这么命名,那 API 文档会变成什么样子?一锅粥。
来看个正确的例子:
# 好的设计
GET /factors # 获取因子列表
POST /factors # 创建新因子
GET /factors/{id} # 获取单个因子
PUT /factors/{id} # 更新因子
DELETE /factors/{id} # 删除因子
GET /factors/{id}/returns # 获取因子的收益序列
# 不好的设计
GET /getAllFactors # 动词混入
POST /createNewFactor # 同上
GET /factor/delete?id=123 # 用 GET 做删除
2.2 HTTP 方法使用:别把 GET 当万能钥匙
HTTP 方法的选择,其实就四个字:各司其职。
| HTTP 方法 | 用途 | 幂等性 | 安全性 | 我踩过的坑 |
|---|---|---|---|---|
| GET | 查询资源 | 是 | 是 | 有人用 GET 传大量参数导致 URL 超长 |
| POST | 创建资源 | 否 | 否 | 重复提交导致数据重复 |
| PUT | 全量更新 | 是 | 否 | 漏传字段导致数据被清空 |
| PATCH | 部分更新 | 否 | 否 | 和 PUT 混用,语义不清 |
| DELETE | 删除资源 | 是 | 否 | 软删除和硬删除没区分 |
这里有个关键点:幂等性。说白了就是「调用一次和调用一百次,结果一样」。GET、PUT、DELETE 都是幂等的。POST 不是。为什么?你想想,你 POST 创建因子,点一次创建一个,点两次创建两个,这能一样吗?
我曾经犯过的错: 在量化回测系统中,用 POST 做「重新运行回测」。结果用户点了一下没反应(网络延迟),又点了一下。好家伙,两个回测任务同时跑,数据库里多了两份一模一样的结果。后来我改成 PUT 了,因为「重新运行」本质上是全量替换,幂等才是对的。
2.3 状态码选择:别只会用 200 和 500
状态码是 API 和调用方沟通的语言。我见过太多项目,不管成功失败,一律返回 200,然后在 body 里塞一个 {"code": 1, "msg": "error"}。这其实是在自废武功。
HTTP 状态码本身就是最好的错误描述,为什么不用?
我常用的状态码清单:
- 200 OK:GET 成功、PUT 成功、PATCH 成功
- 201 Created:POST 创建成功,记得返回 Location 头
- 204 No Content:DELETE 成功,不需要返回 body
- 400 Bad Request:参数校验失败,比如日期格式不对
- 401 Unauthorized:没登录或 token 过期
- 403 Forbidden:登录了但没权限
- 404 Not Found:资源不存在
- 409 Conflict:资源冲突,比如重复创建
- 422 Unprocessable Entity:语义错误,比如因子公式语法不对
- 429 Too Many Requests:限流了
- 500 Internal Server Error:服务端炸了,别让用户看到堆栈
嗯,这里要注意:别把 400 和 422 搞混了。400 是「你发的东西我看不懂」,比如 JSON 格式错误。422 是「我看懂了,但逻辑上不对」,比如因子名称重复了。
2.4 版本控制策略:给 API 留条后路
版本控制,说白了就是「我改了接口,不能让你现有的代码崩掉」。我个人的建议是:用 URL 路径做版本控制,简单粗暴,一目了然。
# 推荐做法:URL 路径版本
GET /api/v1/factors
GET /api/v2/factors
# 不推荐的做法:请求头版本
GET /factors
Headers: Accept: application/vnd.factorfactory.v1+json
为什么我推荐 URL 路径?因为直观。你打开浏览器,看 URL 就知道用的是哪个版本。请求头版本虽然「更 RESTful」,但调试起来太痛苦了。我在项目中用过一段时间请求头版本,结果每次联调都要跟前端说「你加个 Header 啊」,烦死了。
我的版本管理经验:
- 小改动(加字段、加可选参数):不升版本,直接加,客户端忽略未知字段即可
- 中改动(改字段名、改必选参数):升小版本,比如 v1.1,旧版本继续维护一段时间
- 大改动(改接口语义、改数据结构):升大版本,比如 v2,旧版本给足迁移时间
- 永远不要删除旧版本,除非你能确认 100% 没人用了
我曾经在 v1 版本上线半年后,直接把 v1 下线了。结果有个量化研究员写了个定时任务,每天凌晨跑,用的就是 v1。第二天早上他跑过来问我「数据怎么全错了?」。嗯,从那以后我再也不敢随便删旧版本了。
2.5 知识体系总览
下面这张图,是我对 RESTful API 设计原则的总结。你可以把它当成一张「检查清单」,每次设计新接口时对照着看一遍。
这张图把四个核心原则串起来了。你设计 API 时,可以拿它当个「思维导图」。每个分支都过一遍,基本不会出大问题。
一个小技巧: 设计 API 之前,先写一份「API 设计文档」,把资源、方法、状态码、版本号都定下来。让团队 review 一遍再动手写代码。我在团队里推行这个习惯后,返工率至少降了 60%。
好了,RESTful API 设计原则就讲到这里。记住:规范不是束缚,是解放。你按规矩来,调用方舒服,维护方也舒服。下次咱们聊具体的接口实现细节。
公众号:蓝海资料掘金营,微信deep3321