我见过的最烂的API设计,差点让后端同学集体辞职

2026-04-23 16 0

做后端开发这么多年,见过形形色色的API。有的API像优雅的诗句,读起来行云流水;有的API像恐怖片,看一眼做三天噩梦。今天我就来吐槽一下那些让人血压飙升的API设计,顺便分享一些真正有用的设计原则。

一、状态码乱用:200不一定是成功

有一次线上出bug,我翻日志发现接口返回的是200,但用户数据压根没入库。问后端同学,得到的回答是:「哦,那是业务层面的失败,HTTP状态码我们统一用的200。」

我当时就震惊了。200 OK的意思是「服务器成功处理了请求」,不是「业务逻辑执行成功了」。这种设计简直是给调试埋雷——你永远不知道返回200背后藏着什么惊喜。

正确的做法:

// 明确的状态码
200 OK - 请求成功,业务也成功
400 Bad Request - 参数校验失败
401 Unauthorized - 未认证
403 Forbidden - 无权限
404 Not Found - 资源不存在
500 Internal Server Error - 服务器内部错误

// 对于业务层面的失败,用业务错误码
{
  "code": 10001,
  "message": "余额不足",
  "data": null
}

二、命名玄学:让人猜谜的API

我见过最离谱的接口叫 /api/v2/gr。查了半天文档才知道是「获取记录」。说实话,这种命名方式省的是开发者的打字时间,增加的是所有人的理解成本。

API命名应该是不用解释就能懂的。

// 烂命名
GET /api/v2/gr     // 什么鬼
POST /api/sub     // 提交什么?
PUT /api/mod      // 修改什么?

// 好命名
GET /api/v2/goods-reviews           // 获取商品评论
POST /api/v2/orders                 // 创建订单
PUT /api/v2/users/{userId}/profile  // 更新用户资料

三、RESTful?假象罢了

很多人嘴上说着RESTful,实际上做的是「假REST」。比如在一个接口里同时返回用户信息、用户订单、用户收货地址,还要美其名曰「减少请求数」。

RESTful的核心是资源导向:

// 真正的RESTful
GET /users/{userId}              // 获取用户
GET /users/{userId}/orders       // 获取用户的订单
GET /users/{userId}/addresses    // 获取用户的地址

// 假REST(一个接口塞所有)
GET /users/{userId}/full-info-with-orders-and-addresses
// 这玩意儿既不REST,也不优雅

四、分页设计:后端和前端的拉锯战

分页看起来简单,但80%的项目都做得一塌糊涂。常见的问题包括:

1. 用offset做分页,大数据量必翻车

// 烂设计
GET /articles?page=1&limit=20  // 第1页
GET /articles?page=1000&limit=20  // 第1000页?数据库哭了

// 好设计:基于游标的分页
GET /articles?cursor=20240315_abc123&limit=20
// 返回时带上下一页游标
{
  "data": [...],
  "next_cursor": "20240314_xyz789",
  "has_more": true
}

2. 分页响应格式不统一

// 有的接口这么返回
{"items": [...], "total": 1000, "page": 1}

// 另一个接口这么返回
{"list": [...], "totalCount": 1000, "pageNum": 1, "pageSize": 20}

// 第三个接口更绝
{"data": {"list": [...], "count": 1000}}

// 前端同学:我要写多少适配代码?

五、版本管理:没有版本就是最大的版本

很多团队早期不注意API版本管理,等接口要改的时候才发现历史接口不能动,一动就影响线上。这种技术债到后期就是噩梦。

// 路径版本(最常用)
GET /api/v1/users
GET /api/v2/users

// Header版本
GET /users
API-Version: 2024-01-01

// Query版本(不推荐)
GET /users?version=2

六、错误信息:给开发者一条活路

线上出bug了,前端同学来问你:「这个错误码E001是什么意思?」你翻文档,发现文档没写。这就是很多公司的现状——错误码是有了,但错误信息等于零。

// 烂设计
{"error": "E001"}

// 好设计
{
  "code": 10001,
  "message": "当前用户余额不足,无法完成支付",
  "details": {
    "required": 100.00,
    "available": 35.50
  },
  "help_url": "https://api.example.com/docs/errors#PAYMENT_INSUFFICIENT"
}

七、安全那些事

API安全是个老生常谈但总有人踩坑的话题。

1. 敏感数据别放URL里 — GET /users/12345?token=xxxxx 这种设计,token直接暴露在日志里、浏览器历史里、代理服务器日志里。C端能用POST就用POST,或者放到Header里。

2. 接口限流要明确告知 — 超过限流返回429,但很多接口啥提示都不给。应该明确返回:

429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640000000

写在最后

好的API设计就像好的代码注释——不是为了炫技,而是为了让别人(包括未来的自己)能快速理解、轻松使用、少踩坑。

记住几个核心原则:

  • 一致性 — 命名、响应格式、错误处理要统一
  • 明确性 — 返回什么、错误是什么,要说清楚
  • 简洁性 — 一个接口干一件事,别搞全能接口
  • 可演进 — 预留版本机制,别让历史包袱压死自己

API是后端给前端的礼物,设计得好,大家相安无事;设计得烂,你就是团队里那个「差点让后端同学集体辞职」的罪魁祸首。珍爱生命,好好设计API。

有问题欢迎留言讨论,祝大家的接口永远不出bug。(不可能的)

相关文章

AI浪潮里冲浪的小龙虾:新闻、工具和我自己发现的好玩事儿
还在为搭建AI工具折腾到秃头?小龙虾帮你一键搞定!
OpenClaw 使用经验分享:我和这只”数字小龙虾”的日子
懒人福音:让AI工具一键跑起来,是一种什么体验?
AI助手混战实录:谁才是真正的代码搭子?
被这只”虾”圈粉了!我的OpenClaw使用心酸史与真香现场

发布评论