为什么说90%的后端API都是对前端同事的隐性谋杀

2026-10-16 9 0

做了这么多年后端,我有一个不太敢当面说的观点:大多数后端程序员写的API,本质上是一种对前端同事的心理攻击。

你可能不服气。"我写的接口功能齐全,文档完善,返回结构清晰,怎么就成心理攻击了?"

别急,听我说完。


一、你的"统一响应结构"可能是最大的谎言

打开任何一个后端项目的代码,十有八九能看到这样的响应结构:

{
  "code": 200,
  "message": "success",
  "data": {
    // 实际数据
  }
}

看起来很标准对吧?大错特错。

这个结构的致命问题在于:它把业务错误和HTTP状态码的语义混淆了。

当你的接口返回{ "code": 401, "message": "未登录" },同时HTTP状态码是200的时候,前端程序员必须同时解析两个地方才能判断请求是否成功。这不是"统一",这是双重标准。

真正的统一应该是:

  • 业务成功 + HTTP 200
  • 未登录 + HTTP 401 + 专门的error body
  • 参数错误 + HTTP 400 + 详细的校验信息
  • 服务器错误 + HTTP 500 + error_id(方便排查)

不要再用code: 200表示成功了。HTTP状态码本来就是干这个用的,你不用,它就变成了摆设。


二、分页接口:你知道前端拿到的是什么吗?

90%的分页接口是这样的:

{
  "data": [...],
  "total": 1234,
  "page": 1,
  "pageSize": 20
}

看起来很完整。但问题来了:前端其实需要的是渲染分页器,而你只给了总数和当前页。

这意味着前端要自己算:

  • 总页数 = Math.ceil(total / pageSize)
  • 要不要显示"省略号"
  • 当前页是不是第一页/最后一页
  • 如果page=3,总共10页,应该显示哪些页码

这些计算逻辑在前端代码里散落得到处都是,而且很容易出bug。更糟糕的是,如果哪天产品说"要显示前五页和后五页",你得改多少个前端页面?

正确的做法是:后端直接返回前端需要渲染的分页器数据。

{
  "items": [...],
  "pagination": {
    "currentPage": 3,
    "totalPages": 62,
    "hasPrev": true,
    "hasNext": true,
    "pages": [1, "...", 2, 3, 4, 5, "...", 62]
  }
}

这才是真正的服务前端。后端多做一点,前端少崩一点。


三、时间字段:你的格式暴露了你的不专业

我见过最离谱的时间格式:

"createTime": "2024-03-15 16:23:45"
"update_time": "2024/03/15 16:23"
"timestamp": 1710499425

同一个项目里,三种不同格式。这是对前端的酷刑。

标准做法只有两种:

  1. ISO 8601:"2024-03-15T08:23:45Z"——给需要可读性的场景
  2. Unix时间戳(毫秒):1710499425000——给需要计算的内部场景

不要用字符串时间戳,不要用yyyy-MM-dd HH:mm:ss,更不要用秒级时间戳然后假装是毫秒级。

还有,所有时间字段必须明确时区。UTC还是本地时间,必须在文档里写清楚。如果你的系统有时区bug,十有八九是从这个坑开始的。


四、列表接口不返回ID:你让前端怎么玩?

这个问题我遇到太多次了:

// 返回的用户列表
[
  { "name": "张三", "age": 25 },
  { "name": "李四", "age": 30 }
]

// 前端想点进详情页,需要用户的ID...
// 不好意思,没返回
// 不好意思,这个接口不管这个
// 你去调另一个接口查
// 或者,你传name过去,后端模糊匹配?
// ???

列表接口必须返回主键ID。这是常识,但几乎每做一个新项目都会遇到这个问题。

原因往往是后端觉得"列表不需要ID,详情才有",或者是"怕ID泄露"。前者是设计失误,后者是安全感作祟——一个数据库自增ID而已,有什么好藏的?


五、错误信息:请给你的用户留点尊严

最经典的错误返回:

{
  "code": 500,
  "message": "系统异常"
}

或者更离谱的:

{
  "code": -1,
  "message": "操作失败请联系管理员"
}

// 管理员OS: 又是哪个接口报错了?不知道...
// 开发: 哪个接口?
// 管理员: 不知道,错误信息就写了"操作失败"
// 开发: ...

好的错误响应应该包含:

  1. 错误码(业务层面的,区别于HTTP状态码)
  2. 用户友好的中文提示(这个提示是给普通用户看的)
  3. 技术层面的详细信息(只有开启debug模式才返回)
  4. 请求追踪ID(方便定位日志)
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "手机号格式不正确",
    "details": [
      { "field": "phone", "issue": "invalid_format" }
    ],
    "requestId": "req_abc123",
    "docs": "https://api.example.com/docs/errors/VALIDATION_FAILED"
  }
}

六、写在最后

我发现一个规律:后端API的质量,直接反映了这个团队前后端的协作关系。

如果API总是被前端吐槽,大概率是因为后端在设计接口时只考虑了自己的数据模型,完全没想过前端怎么用。如果一个接口设计能让前端用起来舒服,那它大概率也经过了后端的认真思考。

所以,下次写接口之前,问自己三个问题:

  1. 这个接口是为调用方设计的,还是为自己图方便设计的?
  2. 如果我要写前端调这个接口,我会骂人吗?
  3. 这个错误信息,能让前端定位到问题吗?

如果你能诚实地回答这三个问题,你的API质量至少能超过50%的同行。

好的API不是功能的堆砌,而是让调用者用得爽的设计。

共勉。

相关文章

我见过最离谱的API设计,看完我沉默了…
RESTful API设计避坑指南:我用尸体铺出来的经验
你的API报错400,客户当场问候你全家:论Error Response设计
限流:你的服务离崩溃,只差一个双十一
写了5年代码,我依然被这10个API设计问题坑了无数次
熔断器:你服务崩溃前的最后一根稻草

发布评论