为什么你的API总被吐槽?聊聊那些让人想砸键盘的设计

2026-05-17 5 0

为什么你的API总被吐槽?聊聊那些让人想砸键盘的设计

开门见山,我见过太多「能跑就行」的API了。不是我夸张,有些API的设计真的让人怀疑开发者是不是和用户有仇。

今天不整虚的,就聊聊那些年我们踩过的API设计坑,顺便给点靠谱的解决方案。你要是正在写API或者维护API,这篇绝对有用。

一、返回结构:别让客户端去猜谜

先问个问题:你的API成功返回什么?失败返回什么?error字段怎么设计的?

我见过最离谱的API是这样的:

{
  "status": 200,
  "data": {...},
  "message": "操作成功"
}

好,看起来还行对吧?但你试试查个不存在的ID:

{
  "status": 404,
  "data": null,
  "message": "未找到该记录"
}

404是HTTP状态码,但这是一个查询接口啊,查询「未找到」不等于资源不存在啊亲!更可怕的是,前端工程师看到这个200状态码就以为成功了,然后一顿操作猛如虎去访问null里面的字段——恭喜你,喜提线上bug一枚。

我的建议是:HTTP状态码只管通讯层,业务层状态独立设计

{
  "code": 0,
  "message": "成功",
  "data": {...}
}

{
  "code": 40401,
  "message": "用户不存在或已注销",
  "data": null
}

这样前端只需要判断code是否为0,剩下的交给前端自己根据code做业务分流。你好我好大家好。

二、分页:这是一个哲学问题

分页参数怎么设计?offset还是cursor?page还是size?

常见的几种方案:

  • offset/page方案:?page=1&size=20,简单但有坑——删除数据后分页会错位
  • offset方案:?offset=0&limit=20,经典但深分页慢
  • cursor方案:?cursor=xxxxx&size=20,推荐,性能稳定

cursor分页是性能党和数据一致性要求高的场景首选。为啥?你翻到第100页,这时候第50页有人删了一条数据,offset方案的用户就懵了——怎么第50页突然多了一条?

cursor基于位置标识,不存在这个问题。当然cursor也有代价:不能跳页。所以我的建议是:

  • 列表数据需要跳页的,用offset
  • 无限滚动、推荐流这种场景,用cursor

三、命名:代码即文档

API的参数名和返回值名是你给前端兄弟写的文档。

我见过这样的接口:

POST /api/user/update
Body: {
  "nm": "张三",
  "ag": 18,
  "gen": 1
}

你是不是觉得自己很潮?缩写很酷?等到出bug需要排查的时候,或者新来的同事看这段代码,你就知道什么叫技术债了。

命名原则就一条:言出必达,不需要解释

POST /api/users/{user_id}
Body: {
  "name": "张三",
  "age": 18,
  "gender": "male"
}

顺便说一句,URL路径用复数名词是个约定俗成的规矩。/users比/user更符合REST风格,也更一致——你查一个用户是GET /users/{id},查一群用户是GET /users,不需要改变名词。

四、版本管理:沉默的陷阱

你的API v1还在跑吗?v2出来了吗?v1打算什么时候杀?

很多人觉得版本管理是小事,等业务跑起来了才发现:完了,v1的几百个调用方根本不知道要不要迁移,更不敢动。

我的版本策略是这样的:

  • URL路径版本:/api/v1/, /api/v2/,最直观但迁移成本高
  • Header版本:Accept: application/vnd.api.v2+json,优雅但隐蔽
  • Query版本:/api?version=2,门槛最低但不REST

我的建议是:小团队用URL版本,大团队用Header版本。URL版本一目了然,谁在用清清楚楚。Header版本适合多端适配和微服务内部调用。

更重要的是——每个版本都要有明确的废弃时间线。我一般这么定:

  • 新版本发布后,旧版本保守运行6-12个月
  • 提前3个月发公告,告知迁移指南
  • 废弃后保留1个月返回deprecation警告

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

想象一下这个场景:用户下单失败了,API返回「下单失败」。然后呢?前端工程师对着这个错误信息发呆,不知道到底是库存没了、余额不足、还是系统抽风。

错误信息设计原则:给够信息,但不要给废话

{
  "code": "INVENTORY_SHORTAGE",
  "message": "库存不足",
  "details": {
    "requested": 5,
    "available": 2,
    "sku_id": "SKU20250517"
  },
  "support_url": "https://help.comck.com/error/inventory"
}

这个错误信息包含了:

  • 机器可读的错误码(前端可以据此展示不同的UI)
  • 人类可读的错误描述
  • 调试所需的上下文信息
  • 帮助文档链接(减少客服压力)

写在最后

API设计这件事,说难不难,说简单也不简单。核心就一句话:把使用者当人看

你想啊,调用你API的人可能是个刚入行的小前端,可能是个半夜被拉起来处理线上故障的哥们,也可能是一个完全不认识你的第三方开发者。你设计的每一处便利,都是在给他们续命。

下次写API之前,停下来问自己三个问题:

  • 这个名字我自己第一眼能看懂吗?
  • 出错了,调用方能自己定位问题吗?
  • 这个设计,6个月后我自己维护还骂娘吗?

如果三个都是yes,那你这API至少不会被人挂到吐槽社区。做到了这点,你就已经赢了70%的开发者了。

行了,就聊到这儿。有收获的点个赞,没收获的……算了,那是你审美问题不是我技术问题。🙃

相关文章

还在为部署AI工具秃头?让小龙虾帮你搞定一切
还在为部署AI工具秃头?让小龙虾帮你搞定一切
为什么同样配置的服务器,别人能跑你却炸了?一位被连接池坑了三年的工程师的血泪复盘
从“这接口谁写的”到“真香”:RESTful API设计实战复盘
AI探索|当AI开始卷起来,我们都成了吃瓜群众
AI工具部署太麻烦?小龙虾帮你一键搞定,省心又省力!

发布评论