4. 接口设计规范

接口设计这东西,说白了就是给系统之间的对话定规矩。规矩定得好,对接的时候谁都不难受;规矩定得差,嗯,后面全是坑。我在好几个项目里都见过因为接口规范没统一,联调阶段反复返工,最后直接延期上线的情况。

这一章咱们就聊聊接口命名、参数、返回值这些核心规范。我还会对比一下RESTful和RPC两种主流风格,说说各自什么时候用、怎么用。你想想看,SDK本质上就是一套接口集,规范立住了,SDK的质量也就立住了。

4.1 命名规范——一眼看懂接口在做什么

接口命名是第一印象。好的命名,看方法名就知道是查还是改、资源是什么;烂的命名,看完参数还要猜半天。

  • RESTful 风格:资源名用名词复数,用 HTTP 方法表达操作。
    GET    /users          # 查询用户列表
    POST   /users          # 创建用户
    GET    /users/{id}     # 查询单个用户
    PUT    /users/{id}     # 全量更新用户
    DELETE /users/{id}     # 删除用户
    PATCH  /users/{id}     # 部分更新用户
  • RPC 风格:用动词+名词,直接表达动作。
    userService.getUserById
    userService.createUser
    userService.updateUser
    userService.deleteUser

我个人的习惯是:对外公开API优先用RESTful,因为它语义清晰、缓存友好;内部服务间通信用RPC,简单直接、效率高。

命名时还要注意:统一大小写风格(常用小驼峰或蛇形)、避免缩写、版本号放在路径或请求头。

4.2 参数规范——让调用者少翻文档

参数设计做不好,调用方每接一个接口都要去查参数说明。我之前做个支付SDK,有个接口参数列表一长串,大部分还是可选的,结果光联调就花了三天。后来我把必填参数和可选参数分开,把关联参数用对象封装,问题才解决。

4.2.1 必填 vs 可选

必填参数一定要在文档里明确标注,并且如果缺失要返回清晰的错误码。可选参数要有合理默认值。

4.2.2 参数位置

风格 路径参数 查询参数 请求体
RESTful 资源标识(/users/{id}) 筛选、分页(?page=1) 实体数据(JSON)
RPC 不需要 不需要 方法参数封装在请求体

小技巧:分页参数永远统一叫 page、size,排序参数统一叫 sort、order。这样SDK使用者无论对接哪个接口,都不需要重新学习。

4.2.3 参数校验

服务端必须做参数校验。不要信任客户端传来的任何值。我曾经见过一个系统,因为没做参数范围校验,客户端传了个超大数字直接导致数据库OOM——这教训太深刻了。

4.3 返回值规范——成功和失败都要明明白白

返回值设计是最容易被忽视的。很多人只关心成功返回,忘了定义失败长什么样。我建议所有接口都使用统一的数据结构包裹返回内容。

{
  "code": 0,          // 业务状态码,0表示成功
  "message": "ok",    // 人类可读的描述
  "data": { ... }     // 真实业务数据
}

出错的时候也很明确:

{
  "code": 40001,
  "message": "参数校验失败:用户ID不能为空",
  "data": null
}
  • 状态码规范:HTTP状态码 + 业务状态码。HTTP状态码只表达传输层(200成功、400客户端错误、500服务端错误),业务状态码表达业务逻辑。
  • 错误信息:对程序员友好,对用户友好(分场景提供)。
  • 分页返回结构统一:
{
  "code": 0,
  "data": {
    "items": [...],
    "total": 100,
    "page": 1,
    "size": 20
  }
}

4.4 RESTful vs RPC 风格选择

选哪个?没有银弹。我踩过不少坑总结出来下面这张表:

对比维度 RESTful RPC
语义表达 资源 + 操作 方法名 + 参数
缓存友好 是(HTTP缓存) 否
性能 中等(需解析URL) 高(二进制序列化)
学习成本 低(遵循Web标准) 中等(需了解IDL)
典型场景 对外API、Web应用 内部微服务、网关

注意:不要在同一套SDK里混用两种风格。我见过有人前半段用RESTful,后半段用RPC,结果调用方搞不清楚该用GET还是该传对象。风格一致比风格完美更重要。

4.5 一张图看懂接口设计规范

接口设计规范核心维度 接口规范 命名规范 参数规范 返回值规范 风格选择 RESTful 风格 RPC 风格 一致性比风格本身更重要,不要混用

4.6 避坑指南

我这几年在接口设计上踩过的坑,总结成几条给你参考:

  • 命名不要变:一旦发布,接口名和路径就再也不要改了。改一次,所有客户端都要跟着升级SDK。我曾经在一个开放平台,把 getUser 改成了 fetchUser,结果被合作伙伴投诉了一个月。
  • 返回值结构不要中途变:新增字段可以,但不要改已有字段的类型、含义或位置。特别是不要从数组改成对象,或者从字符串改成数字——这些破坏性改动会让序列化直接崩溃。
  • 错误信息要稳定:不要在错误信息里带数据库字段名、堆栈信息。统一返回可读的业务描述,并且为每个错误定义固定的业务码。
  • 版本控制要提前做:接口路径或请求头里带上版本号(如 /v2/users),这样即使后面要大改,旧版本也能继续运行一段时间。

一个小建议:设计接口的时候,把自己想象成SDK的使用者。你能一眼看明白这个接口怎么调用吗?你的参数列表会不会让IDE提示太长?你的错误信息能不能帮问题定位?想清楚这些,规范自然就到位了。