用途
该技能用于在设计 API、模块边界或任何公共接口时提供指导,目标是创建稳定、文档完善且“难以误用”的接口。适用范围包括 REST API、GraphQL schema、模块边界、组件 props,以及任何一段代码与另一段代码交互的界面。
触发场景
资料列出以下适用时机:
- 设计新的 API 端点
- 定义模块边界或团队之间的契约
- 创建组件 prop 接口
- 建立影响 API 形态的数据库 schema
- 变更已有的公共接口
核心原则
Hyrum 定律
当 API 拥有足够多用户时,系统中所有可观察行为都会被某些人依赖,无论契约中承诺了什么。因此未文档化的怪癖、错误消息文本、时序和顺序都可能成为事实契约。设计含义包括:对暴露内容保持刻意;不要泄露实现细节;在设计阶段规划弃用;测试不足以覆盖此类风险。
单一版本规则
避免迫使消费者在同一依赖或 API 的多个版本之间选择。菱形依赖问题出现在不同消费者需要不同版本时。应设计为同一时间只存在一个版本,通过扩展而非分叉来演进。
主要设计要点
-
契约优先:先定义接口再实现;契约即规范,实现跟随。资料给出 TaskAPI 的 TypeScript 接口示例,包含创建、列表、获取、部分更新和幂等删除。
-
一致的错误语义:选择一种错误策略并全局使用;资料给出 APIError 结构(code、message、details)及状态码映射(400、401、403、404、409、422、500),并提醒不要混用抛异常、返回 null、返回 { error } 等模式。
-
在边界校验:信任内部代码,只在外部输入进入的系统边缘校验,包括 API 路由处理器、表单提交、外部服务响应解析和环境变量加载。第三方 API 响应应视为不可信数据,使用前需校验形状与内容。不应在共享类型契约的内部函数之间、已被校验代码调用的工具函数中、或来自自身数据库的数据上重复校验。
-
优先新增而非修改:通过添加可选字段扩展接口,避免更改已有字段类型或删除字段。资料给出 CreateTaskInput 的正反示例。
-
可预测命名:REST 端点使用复数名词、不带动词;查询参数 camelCase;响应字段 camelCase;布尔字段使用 is/has/can 前缀;枚举值使用 UPPER_SNAKE。
-
遵守幂等键:接受 Idempotency-Key 是契约,正确履行是实现。键应从意图派生而非每次尝试重新生成;资料给出正反示例(randomUUID、用户+金额、订单+时间戳为错误;客户端生成一次并在重试中复用、从不可变标识符派生为正确)。
REST API 模式
资料给出资源设计示例:GET /api/tasks 列表、POST /api/tasks 创建、GET /api/tasks/:id 获取、PATCH /api/tasks/:id 部分更新、DELETE /api/tasks/:id 幂等删除。每个列表端点必须支持分页,并给出 PaginatedResponse<T> 的响应结构示例。
常见合理化与红旗
资料列出常见借口及现实反驳,例如“实现时再设计 API”“需要时再版本化”“没人用未文档化行为”“可以维护两个版本”“内部 API 不需要契约”。红旗包括:端点返回形状随条件变化、错误格式不一致、校验散落内部代码、破坏性字段变更、列表端点无分页、REST URL 含动词、第三方响应未校验、幂等键先 SELECT 再 INSERT 的竞态、键由 UUID 或时间戳派生。
设计后验证清单
资料提供验证项:每个端点有类型化输入输出 schema;错误响应格式统一;校验仅在系统边界;列表端点支持分页;新字段为可选的增量添加;命名一致;API 文档或类型随实现提交;状态变更端点遵守幂等键或明确标注不可安全重试;键以原子操作声明并由唯一约束保护;重用键但载荷不同时显式失败;键保留时间超过最长重试路径(含死信重放)。
限制
资料未提供该技能的安装方式、运行环境、收费模式或具体平台支持信息。