上线前一天发现:A 团队等 B 的字段上线,B 团队等 A 改调用方,两边都以为对方在做。最后谁都没做,也没人违约——因为从来没人明确承诺过。
跨团队协作的故障几乎都不是能力问题,而是承诺没有被写成可检验的东西:接口文档通常有,时限只在口头,应急约定根本不存在。
1. 三种契约,缺的往往不是接口那种
| 契约 | 承诺什么 | 最容易缺失的部分 |
|---|---|---|
| 接口契约 | 字段、语义、错误码、兼容窗口 | 语义与错误码,而不是字段名 |
| 时限契约 | 交付日期、变更冻结期、响应时长 | 冻结期与响应时长 |
| 应急契约 | 出事谁先看、多久响应、谁能关 | 谁有权限关、谁能降级 |
接口契约表面上最受重视,实际最容易做成“字段清单”:字段名对得上,语义对不上。调用方按 status=1 读成成功、提供方读成“已受理”,联调才炸。
时限契约的缺口是冻结期:双方都写“X 月 X 日交付”,却没写“交付前 N 天冻结接口”,于是交付前一天提供方还在改字段。
应急契约最彻底地缺席:它回答的不是“出事了怎么办”,而是“谁有权在没达成一致时先动手”——谁能关开关、回滚、拒绝对方的紧急变更。
2. 承诺的四要素与只写前两个的后果
| 要素 | 写清楚的样子 | 只写内容的后果 |
|---|---|---|
| 内容 | 提供什么、什么格式、什么语义 | 双方各自理解,联调时才发现 |
| 时间 | 什么时候可用、何时冻结 | "做完了"没有基准,永远差一天 |
| 质量 | 多快、多准、多少比例可失败 | 上线后为性能与错误率互相指责 |
| 失效条件 | 什么情况下承诺作废 | 承诺被当成永久义务,谁都不敢改 |
commitment:
from: team-b # 提供方
to: [team-a, team-c] # 消费方,必须列全
content: "order.query v2 返回 items[].refund_status"
quality: { p99_ms: 80, error_rate: "< 0.1%" }
time: { available: 2026-03-10, freeze_from: 2026-03-03 }
invalid_when: # 失效条件,缺这一段等于永久承诺
- "依赖的上游字段被删除"
- "消费方 P99 目标下调到 50ms 以下"
verify: "契约测试 + 每周一次影子流量比对"
失效条件最容易被当成“不友好”,但它恰恰是承诺能长期维持的原因。没有它的承诺签的时候爽快,半年后没人敢执行——执行就等于毁约。
判据:一份承诺若说不清它在什么情况下不算数,它就不是承诺,是愿望。
3. 接口归谁定义:提供方还是消费方
| 模式 | 谁定字段形状 | 代价 |
|---|---|---|
| 提供方定义 | 提供方按内部模型设计 | 内部模型泄漏,改内要先改外 |
| 消费方定义 | 消费方按用例提字段 | 多方拉扯,字段膨胀成并集 |
| 折中(推荐) | 消费方提需求、提供方定形状、共管兼容窗口 | 需要仲裁角色 |
提供方定义的典型症状是内部模型外泄:库表字段名、枚举值直接出现在对外接口上,于是“改个索引顺序”成了破坏性变更。
消费方定义的典型症状是字段并集:三个消费方各要一点,40 个字段里 30 个只有一个人用,谁都不敢删。
折中的关键是兼容窗口有人管:谁批准废弃、公告多久、旧字段留几版。这角色不落到人头上,窗口就会无限延长。
4. 内部 SLA 多半是政治承诺
内部 SLA 的判据不是数字,而是有测量点、有预算、违约有后果三件事同时成立。缺一条,它就不是技术保证。
| 形态 | 表现 | 实际效果 |
|---|---|---|
| 有目标值、无测量 | 文档写 99.9%,无人算达成率 | 出事后各用对自己有利的口径 |
| 有测量、无预算 | 达成率低就"加强重视" | 提供方靠加班兜,直到兜不住 |
| 有预算、无后果 | 预算烧完照常接需求 | 预算变成报表装饰 |
| 三者齐备 | 预算耗尽即冻结新需求 | 唯一能自我维持的形态 |
第四条才可持续:预算烧完,提供方有权拒绝新需求并优先稳定性。没有这条,SLA 只是复盘会上被引用的台词。
另一个失真来源是口径:按请求还是按分钟、部分失败算不算。口径不写进契约,达成率就可谈判。
5. 依赖清单与方向可视化
team-a → team-b(order.query) 强依赖 可降级=否 备用=缓存旧值
team-a → team-c(user.profile) 弱依赖 可降级=是 备用=默认头像
team-b → team-a(stock.sync) 强依赖 可降级=否 备用=无 ← 双向,注意
清单里最该标的是后两列:能否降级、有无备用路径。缺了它们,依赖清单只是架构图,看不出影响面。
方向比数量更重要。单向依赖可以自治;双向强依赖会让两团队发布永久耦合。处理只有两条:一条改异步消息,或两块合到一个团队。
判据:强依赖超过 3 个,自治就是空话。发布窗口要对齐 3 个团队,等于没有窗口。
6. 三种通知机制与退出条件
| 机制 | 适用 | 代价 | 必须写的退出条件 |
|---|---|---|---|
| 提前公告 | 破坏性变更、消费方需改代码 | 慢,需要冻结期 | 公告期满 + 全部消费方确认 |
| 灰度共存 | 字段演进、协议升级 | 双写与适配成本 | 旧版本流量归零 N 天后下线 |
| 直接切换 | 内部实现、确认无消费者 | 隐藏消费者会当场炸 | 无(但要先证明无消费者) |
三种机制里,灰度共存最易变成永久状态:双版本跑着,谁都不想承担下线风险,半年后两套逻辑都在改。共存必须自带退出条件与截止日期,否则它是负债而不是过渡。
直接切换的判据不是“应该没人用”,而是“能证明没人用”:网关日志、契约测试的消费方清单、最近 N 天调用来源。都没有,就按有隐藏消费者处理。
7. 阻塞的识别与升级路径
L0 对接人直连 触发:任一方等待 > 1 个工作日
L1 双方 leader 触发:同一问题第二次未在承诺时间内闭环
L2 架构/项目负责人 触发:影响跨 3 个以上团队,或需要变更已冻结的承诺
L3 决策会 触发:需要取舍优先级或砍需求
升级判据只有一个:同一问题第二次没在承诺时间内闭环。第一次可以等,第二次必须升级——“再等一次”的期望收益已被证伪。
反模式是把升级当成关系破裂,于是大家默契地拖着,问题在末期一次爆发,只剩延期或砍功能。
升级到谁比何时升级更重要:对象必须是能改变优先级的人,而不是“更资深的同级”。找同级诉苦只会增加沟通量。
8. 联合复盘:不追责,但要改流程
四问(每问必须有具体事件,不接受"沟通不畅"):
1 哪一次交接双方的理解不一致?谁在什么时候发现了?
2 哪个假设没有验证就被当成事实?验证成本是多少?
3 哪条承诺没写失效条件或质量指标?
4 哪一步流程改动能让同类问题不可能再发生?
输出必须是一条流程改动 + 责任人 + 生效日期。写“加强沟通”等于没做——无法验证,也无法撤回。
不追责要落到机制上:记录不写人名只写角色,不统计“谁的问题多”,结论进流程文档而非绩效材料。一旦用于考核,下一轮只剩互相防御。
9. 协作成本随团队数量增长
n 个团队两两沟通,通道数是 n(n−1)/2:
n=3 → 3 条 可全连
n=6 → 15 条 开始出现"没被通知到"
n=10 → 45 条 必须引入接口人
n=20 → 190 条 全连不可行,只能靠分层
削减手段按性价比排序:
| 手段 | 效果 | 代价 |
|---|---|---|
| 减少依赖(合并职责) | 直接把 n 变小 | 需要接受更大的单团队边界 |
| 接口人(hub 模式) | 把 n² 降为 2n | 接口人成为瓶颈与单点 |
| 统一契约与工具链 | 降低单次沟通成本 | 前期投入大,收益滞后 |
| 加会议 | 几乎无效 | 占用所有人时间 |
最容易做的是加会,最没用:会议只能传递信息,替代不了承诺——承诺要被写下并验证。
10. 度量跨团队协作
跨团队变更前置时间 = 提出需求 → 消费方上线可用 (按变更类型分桶)
返工率 = 因理解不一致而重做的变更 / 总变更
阻塞时长 = 等待对方响应/交付的累计工作日
承诺兑现率 = 按承诺时间与质量交付的条目 / 总条目
四个指标里返工率最能暴露契约质量问题,直接对应“字段名对上但语义没对上”。前置时间看趋势,不看单次。
度量要按团队对拆分,汇总会把“A 与 B 的问题”稀释成“整体还行”。
11. 排错:协作失灵的六种样子
| 现象 | 根因 | 处理 |
|---|---|---|
| 上线前互相等待 | 承诺只在口头 | 写承诺卡,带时间与质量 |
| 联调时语义不一致 | 契约只有字段清单 | 补语义与错误码 |
| 变更频繁打断对方 | 没有冻结期 | 设冻结窗口 |
| 事故时互推责任 | 无应急契约 | 明确谁有权关 |
| 灰度版本下不掉 | 共存无退出条件 | 写截止日期 |
| 复盘后同样问题再犯 | 结论是“加强沟通” | 流程改动+责任人 |
12. 边界:契约管理收益有限的地方
| 场景 | 判断 | 替代做法 |
|---|---|---|
| 同一团队内的模块 | 有共同上级 | 代码评审+接口注释 |
| 纯外包、无协商空间 | 承诺不可谈判 | 只保留验收标准 |
| 一次性项目 | 维护成本高于收益 | 一份交付清单 |
| 团队数 ≤ 2 且稳定 | 通道只 1 条 | 定期同步+共享看板 |
| 同一发布单元的强耦合 | 拆开增加契约面 | 合并发布 |
最后一类值得强调:把同生共死的发布单元拆成两个团队的契约,只会把一次发布变成两次协商。边界该跟发布单元走,不是跟组织结构走。
13. 自测
- 三种契约里哪一种在你组织里几乎没被写过?后果是什么?
- 承诺只写了内容和时间,缺质量与失效条件,半年后会怎样?
- 接口由消费方定义,最典型的长期后果是哪一种?
- 内部 SLA 要成立,除测量点之外还必须有什么?
- 升级触发条件为什么定在“第二次未闭环”,而不是第一次?
- 团队从 6 个扩到 10 个,通道数多少,你会先做哪件事?