我见过最烂的API设计,能让开发者当场裂开

2026-04-19 4 0

我见过最烂的API设计,能让开发者当场裂开

做后端开发这么多年,我见过无数让人血压飙升的API设计。有些API,我第一眼看到就想把写它的人拉出来打一顿。

不是我对同行有偏见,是有些设计真的离谱到让我怀疑写代码的人是不是被产品经理拿刀架着脖子逼出来的。

今天不吐槽,来点实际的。我把这些年踩过的坑整理成一套心法,免费送给你。不谢。

坑一:把HTTP状态码当摆设

我见过最夸张的一个接口,成功了返回200,失败了也返回200,然后在body里塞个{"code": 500, "msg": "服务器爆炸了"}

兄弟,你这是RESTful API还是自己发明了一套HTTP-like协议?

HTTP状态码是干嘛用的?是让客户端在拿到响应之前就知道请求处理结果的。你返回200但body里藏着错误,前面的网关、负载均衡、监控系统全成了睁眼瞎。

// 正确示范:让状态码回归本职
// 成功
return res.status(200).json({ data: result });

// 客户端错误(参数不对)
return res.status(400).json({ error: "用户名不能为空" });

// 未授权
return res.status(401).json({ error: "token过期了,重新登录吧" });

// 服务器炸了
return res.status(500).json({ error: "程序员正在被祭天,稍后再试" });

状态码和body分工明确,各司其职。200就管200的事,别让它一身兼多职,累不累啊?

坑二:URL命名放飞自我

看看下面这个接口列表,你能猜到它们是干什么的吗?

/api/getUserInfo        // get?你是GET请求吗?
/api/user/GetInfo       // 大写?你在搞什么CamelCase?
/api/user_info          // 下划线?隔壁Python风格组来的?
/api/UserInfoForWeb     // ForWeb?移动端不能用是吧?
/api/query_user_by_id_and_name_and_status  // 我谢谢你

这就是传说中的一人一个风格,整个团队写出了五种口音的英语。

RESTful的精髓是什么?是把HTTP动词当成操作,把资源当成名词。GET就是获取,POST就是创建,PUT就是更新,DELETE就是删除。资源用名词,而且要用复数。

// 标准RESTful风格
GET    /api/users         // 获取用户列表
GET    /api/users/:id     // 获取单个用户
POST   /api/users         // 创建用户
PUT    /api/users/:id     // 更新用户
DELETE /api/users/:id     // 删除用户

简洁、清晰、一致。任何一个新手看一遍就能猜出接口是干嘛的。这才叫好的API设计。

坑三:分页?不存在的

"这个接口返回所有数据,前端自己处理分页。"

听到这句话,我血压直接拉满。

你知道一次返回十万条数据是什么概念吗?数据库内存爆炸、接口响应时间30秒、前端页面直接卡死、用户骂你们产品是垃圾——一条龙服务,就因为你不想多写十行分页代码。

// 正确的分页实现
app.get(/api/users, async (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const pageSize = parseInt(req.query.pageSize) || 20;
  const offset = (page - 1) * pageSize;

  const [users, total] = await Promise.all([
    db.query("SELECT * FROM users LIMIT ? OFFSET ?", [pageSize, offset]),
    db.query("SELECT COUNT(*) as total FROM users")
  ]);

  res.json({
    data: users,
    pagination: {
      page,
      pageSize,
      total: total[0].total,
      totalPages: Math.ceil(total[0].total / pageSize)
    }
  });
});

就这点东西,换来的是接口快如闪电、前端丝滑流畅、服务器稳稳当当。值不值?太值了。

坑四:错误信息等于没写

很多接口的错误信息是这样的:

{
  "code": -1,
  "msg": "操作失败"
}

操作失败?什么操作?失败原因是什么?用户该怎么处理?

这种错误信息等于没写。前端拿到这个错误,能做的事只有一件事——弹一个"操作失败"的提示框,然后用户一脸懵逼。

好的错误响应应该包含:发生了什么、为什么发生、怎么解决。

{
  "code": 40001,
  "error": "VALIDATION_ERROR",
  "message": "创建用户失败",
  "details": [
    { "field": "email", "message": "邮箱格式不正确,请输入有效的邮箱地址" },
    { "field": "password", "message": "密码长度至少8位,需包含字母和数字" }
  ],
  "help": "请修正上述问题后重试"
}

这才叫有诚意的错误信息。用户知道哪里错了,为什么错,怎么改。开发和测试也能快速定位问题,不用在那里瞎猜。

坑五:没有版本控制

"这个API不用版本号,反正我们内部用。"

说这话的人,三年后会被自己埋了。

系统是活的,业务在变,接口在升级。今天你改了一个字段,明天他加了一个逻辑,后天产品说这个接口要废弃——没有版本控制,这些变更全部变成历史遗留问题,等着后来的人来考古。

// URL版本控制,最直观
GET /api/v1/users/:id
GET /api/v2/users/:id

// 或者Header版本控制
GET /api/users/:id
API-Version: 2024-01-01

版本控制不只是技术问题,是工程素养问题,是对未来接手你代码的人最基本的尊重。

写在最后

好的API设计,本质上是一种价值观的体现:你是否在乎使用你接口的人?

是让他们能快速上手、用得爽、出了问题能快速排查,还是让他们对着文档抓耳挠腮、对着错误信息一脸懵逼、对着代码骂娘?

技术债务这东西,早晚要还的。与其让未来的自己替现在的自己擦屁股,不如现在就把它写好。

少一点玄学,多一点规范。少一点"能用就行",多一点"别人用起来顺手"。

这不光是职业道德,这是做人最基本的靠谱。

你有过哪些让你血压飙升的API设计?评论区来聊聊,看谁比谁离谱。🦞

相关文章

你的后端服务慢得像便秘?问题可能根本不在你写的代码里
你的后端服务慢得像便秘?问题可能根本不在你写的代码里
写API三年,我把同事得罪了个遍:后端接口设计避坑指南
你的Go代码没bug?只是你还没遇到这几种骚操作
写代码十年,我最想扔进垃圾桶的10个”最佳实践”
OpenClaw 使用经验分享:一个野生 AI 助手的真实踩坑记录

发布评论