4. 接口契约的定义要素:入参、出参、异常、前置条件、后置条件、幂等性
接口契约是模块之间进行通信的“书面合同”,它不关心模块内部的实现细节,只定义通信双方必须遵守的条款。当你对两个模块进行接口划分时,真正切分的是这些条款的归属与严格程度。
一份完整的接口契约由六个要素构成,缺少任意一个都会导致协作模糊或系统不可靠。
核心论点:入参和出参描述数据形态;异常描述失败模式;前置条件和后置条件描述副作用与状态约束;幂等性描述可重试性。只有六要素齐全,接口才能被视为“签署完成”。
4.1 六要素的定义与边界
| 要素 | 定义 | 在架构层面的关注点 |
|---|---|---|
| 入参 | 调用方传入的数据集合,包含必填、可选、默认值、格式、范围 | 入参的验证责任归属(调用方 vs 提供方);参数膨胀趋势 |
| 出参 | 被调用方返回的数据集合,包含成功响应与业务数据 | 返回结构的稳定性;是否存在调用方不需要的数据泄露 |
| 异常 | 接口在非预期情况下向外暴露的错误类型、错误码、错误消息 | 异常的分类粒度;调用方能否根据异常做出正确重试或降级 |
| 前置条件 | 调用前必须为真的状态,例如“用户已认证”“订单处于待支付状态” | 前置条件由谁保证;违反时是被调用方拒绝还是调用方自行检查 |
| 后置条件 | 调用成功后必定为真的状态,例如“余额已扣减”“库存已锁定” | 后置条件的原子性;是否可能因部分失败导致状态不一致 |
| 幂等性 | 同一请求多次执行的结果与执行一次的结果相同 | 幂等键的方案选择(业务主键 vs 请求ID);幂等的存储边界 |
4.2 要素之间的依赖与信任链路
接口契约的六个要素不是孤立存在的,它们共同构成了调用方与被调用方之间的信任链路:
- 调用方视角:先校验入参,确保前置条件满足;发送请求后,通过出参和异常判断结果;根据幂等性决定是否重试。
- 被调用方视角:接收入参,验证前置条件;执行业务逻辑,确保后置条件达成;返回出参或在异常时抛出明确错误。
- 信任断点:任何一个要素的模糊都会导致信任断裂。例如,未定义幂等性时,调用方不敢在网络超时后重试;未定义后置条件时,调用方无法确认业务是否完成。
4.3 要素的选型权衡与风险点
每个要素在落地时都存在典型的权衡和风险:
- 入参:是否允许调用方传入冗余字段?过度宽松的入参导致提供方承担不必要的验证逻辑;过于严格则降低接口的复用性。
- 出参:是否返回全量数据还是一部分?全量返回增加传输负担和数据泄露风险;部分返回可能导致调用方多次请求获取完整信息。
- 异常:异常粒度应该细致到每个业务码,还是粗粒度地分为成功/失败?细粒度异常有助于调用方精细处理,但也增加了调用方的分支复杂度。
- 前置条件:是否由被调用方主动验证?若被调用方不做验证,而是依赖调用方保证,那么前置条件就失去了契约意义。
- 后置条件:是否保证原子性?例如“扣费并发送通知”并非由同一个模块的后置条件保证时,需要引入分布式事务或最终一致性方案。
- 幂等性:幂等键存储在哪里?内存存储导致重启后失效;数据库存储带来性能开销。选择时需要权衡重试窗口长度与存储成本。
常见反模式:将“时间戳”作为幂等键。时间戳在毫秒级重复的概率很高,且无法区分业务含义。请使用全局唯一ID或业务主键。
4.4 落地步骤
- 第一步:列出所有接口的六要素清单。用表格或模板记录每个接口的入参结构、出参结构、异常码列表、前置条件、后置条件、幂等策略。创建一份契约登记表,作为模块划分的交付物之一。
- 第二步:确定每个要素的严格程度。核心链路(如支付、订单)六要素必须全部明确;非核心链路(如日志查询)可以适当简化(例如不定义幂等性)。
- 第三步:前置条件和后置条件的语法化。将自然语言描述的状态转换为可编码的表达式,例如“订单状态 == ‘待支付’ AND 用户余额 >= 商品金额”。
- 第四步:异常分类与错误码设计。按照“业务码前缀 + 错误类型 + 错误序号”的层级结构设计错误码,为调用方提供可编程的识别能力。
- 第五步:幂等性方案选择与实现。根据业务场景决定使用“请求ID去重”还是“业务主键幂等”,并明确幂等键的生成方与存储位置。
- 第六步:契约验证。通过单元测试或接口模拟器验证:前置条件未满足时接口是否拒绝;多次重试是否产生重复数据。
4.5 验收标准
模块划分完成并交付接口契约时,必须满足以下验收条件:
| 验收项 | 验收标准 |
|---|---|
| 六要素完整性 | 每个接口的入参、出参、异常、前置条件、后置条件、幂等性均已在契约文档中定义 |
| 前置条件可检查 | 被调用方能够根据入参和当前系统状态独立验证前置条件 |
| 后置条件可验证 | 调用方能够在接收到正常出参后,验证业务状态是否符合后置条件 |
| 异常可分类处理 | 调用方可以根据错误码区分“可重试”“不可重试”“降级处理”等不同策略 |
| 幂等性可验证 | 重复请求测试后,业务数据没有产生多余记录或重复状态变更 |
实践建议:在接口设计评审阶段,用六要素清单作为检查列表逐项确认。缺少任何一项,都不应签署契约。这是防止模块间依赖混乱的最有效手段。