Level 42 / 阅读练习

接口契约、版本管理和文档

理解接口契约、OpenAPI、字段变更、版本管理、错误码和契约测试。

Progress

阅读中

0/2 步完成 / 阅读后完成练习才算通关

Practice

本关怎么过

  • 读完正文后确认完成阅读
  • 完成 1 道选择题练习
  • 答错时看解释,再回到正文补理解

一句话:接口契约就是前后端共同遵守的约定,版本管理和文档是为了让这个约定在项目变大、人员变多之后仍然不乱。

本篇学完你会什么:知道接口文档应该写什么,字段变更怎么不坑前端,为什么要有版本号,以及如何用 OpenAPI、示例和契约测试减少联调成本。

1. 接口契约是什么

接口契约就是前后端之间的合同。

它至少约定:

请求地址
请求方法
请求参数
请求头
响应结构
错误码
权限要求
分页规则
字段含义

如果没有契约,联调时就会变成:

前端:你这个字段怎么没返回?
后端:我以为你不用。
前端:错误码为什么变了?
后端:我昨天顺手改了。

契约不是为了写文档而写文档,而是为了减少猜。

2. 一份好接口文档要写什么

以用户列表接口为例:

GET /api/v1/users?page=1&page_size=20&keyword=tom
Authorization: Bearer <token>

文档应该包含:

内容示例
接口用途查询用户列表
权限要求user:read
请求方法GET
请求路径/api/v1/users
Query 参数pagepage_sizekeyword 的类型、默认值和范围
响应字段itemstotalpagepage_size 的类型和含义
错误情况401、403、422
示例请求带真实参数
示例响应带完整字段

示例响应:

{
  "items": [
    {
      "id": 1,
      "username": "tom",
      "email": "tom@example.com",
      "is_active": true
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 20
}

文档里不要只写字段名,还要写含义。

3. 字段变更为什么容易出问题

接口最怕“悄悄变”。

危险变更:

变更为什么危险
删除字段前端读不到会报错
字段改名前端旧代码不认识
类型改变number 变 string 会影响计算
枚举新增前端没有展示逻辑
错误码改变前端提示和流程失效
分页结构改变列表页直接坏

更安全的变更方式:

先新增字段,不立刻删除旧字段
前端切到新字段
观察一段时间
再移除旧字段

比如:

{
  "username": "tom",
  "display_name": "Tom"
}

不要直接把 username 改成 display_name

4. 接口版本怎么设计

常见版本方式:

/api/v1/users
/api/v2/users

什么时候需要新版本?

场景是否需要新版本
新增可选字段通常不需要
新增接口不需要
删除字段可能需要
响应结构大改需要
认证方式变化需要
业务语义变化需要

不要每次小改都加版本。版本太多会让维护变复杂。

推荐原则:

兼容性新增 -> 留在当前版本
破坏性变化 -> 新版本或分阶段迁移

5. OpenAPI 和契约测试怎么用

FastAPI 会自动生成 OpenAPI:

/docs
/openapi.json

但自动文档不是全部。你还要把这些写清楚:

from pydantic import BaseModel, Field


class UserListItem(BaseModel):
    id: int = Field(description="用户 id")
    username: str = Field(description="登录名")
    email: str | None = Field(default=None, description="邮箱")
    is_active: bool = Field(description="是否启用")

契约测试可以简单理解为:

用测试确认接口返回结构没有乱变。

示例:

def test_user_list_contract(client, admin_token):
    response = client.get(
        "/api/v1/users",
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    assert response.status_code == 200
    data = response.json()
    assert "items" in data
    assert "total" in data
    assert "page" in data
    assert "page_size" in data
    assert isinstance(data["items"], list)
    assert isinstance(data["total"], int)
    assert isinstance(data["page"], int)
    assert isinstance(data["page_size"], int)

这个测试仍然很简化。真实项目还会检查 items 里每个用户对象的字段,比如 id 是数字、username 是字符串、is_active 是布尔值。它不是替代业务测试,而是守住前后端约定。

6. 前后端协作流程

一个实用流程:

  1. 后端先写接口草案:路径、字段、错误码。
  2. 前端看草案,确认页面需要的字段够不够。
  3. 双方确认后再开发。
  4. 后端提供 mock 或测试环境接口。
  5. 前端按契约接入。
  6. 联调时只修偏差,不临时改约定。
  7. 接口变更必须同步文档和测试。

字段变更建议写清:

新增字段:什么时候可用
废弃字段:什么时候移除
破坏性变化:影响哪些页面
迁移方式:前端如何兼容

7. 常见错误

错误后果修正
只靠口头约定联调反复猜写接口契约
文档没有示例字段含义不清楚加请求和响应示例
字段悄悄改名前端线上报错先新增后废弃
错误码不稳定前端提示混乱统一错误码
每次小改都升版本版本维护复杂只给破坏性变化升版本
自动文档字段没描述看不懂业务含义给 Pydantic 字段加说明

8. 检查清单

[ ] 接口有路径、方法、权限说明
[ ] 请求参数有类型、是否必填、示例
[ ] 响应字段有含义说明
[ ] 错误码和错误消息有约定
[ ] 分页结构统一
[ ] 破坏性变化有迁移计划
[ ] OpenAPI 能正常生成
[ ] 关键接口有契约测试
[ ] 文档和代码变更一起提交

9. 小结

名词大白话
接口契约前后端共同遵守的合同
OpenAPI接口机器可读说明书
契约测试防止接口结构偷偷变
兼容性变更不影响旧前端的新增
破坏性变更会让旧调用方坏掉的变化
版本管理管住接口长期演进

上一篇建议:先看《数据库备份、迁移和恢复》。

下一篇建议:继续看《生产问题排查 Runbook》,把线上故障处理流程补齐。

Checkpoint

读完后做题闯关

先读正文,再用下面的选择题检查自己是否真的理解。答错会出现解释,可以回到正文补一眼再重选。

0/1
先完成阅读

读完正文后点击“我已读完,进入练习”,题目会变成可答状态。

第 1 题

读完这一篇后,最适合怎么确认自己真的理解了?