Skip to the content.

核心概念

理解四个词就能读懂整份报告:契约、使用点、传播、风险与置信度。

契约(Contract)

契约是两个程序共同依赖的、有明确身份的东西。它不属于任何一方,而是双方的约定。

本工具识别六类契约:

契约 身份是什么 例子
HTTP 接口 规范化路径模板 GET /api/users/{}
数据库字段 表.字段(table.column) orders.status
配置项 配置 key app.limit
Maven 依赖 artifactId common
消息主题 Topic / Exchange / Queue order.created
消息 Schema 消息体结构指纹 OrderEvent

数据库契约以字段为单位,不是以表为单位:本程序给自己多查一列属于内部行为,对方看不见, 不算契约变化。字段级匹配前还要确认两侧是同一数据库对象(JDBC URL / 显式 schema),并且只让 「对方能观察到」的变更扩散:删列、收窄类型命中读写方,加列、建表、类型放宽不扩散。 只有 DROP TABLE 这种字段未知的整表变更,才退回按表名匹配。

为什么契约是关键? 两个仓库编译期互不可见,它们唯一的联系方式就是这些共享标识。 所以”是否影响对方”这个问题,可以精确化为”本次改动是否改动了某个契约,而对方是否在用它”。

使用点(Usage)

对方程序里真正读到或写到这个契约的位置。

使用点决定了影响的起点。没有使用点,契约改得再狠也不影响对方。

传播(Propagation)

影响不止于直接使用点。如果 UserClient#fetchUser 受影响,那么调用它的 OrderService#canOrder 也受影响——这是在对方程序自己的调用图里做的反向遍历。

本程序改动
   ↓ 命中契约
UserClient#fetchUser        ← 直接使用点(深度 1)
   ↑ 反向调用边
OrderService#canOrder       ← 传播结果(深度 2)

两条重要规则:

  1. 只在对方图里传播。 不会回到本程序,也不合并两张图——它们本来就不连通。
  2. 用法决定权重。 返回值参与分支(CONDITION)权重 1.0,只打日志(LOG_ONLY)权重 0.2。 同样是调用,后果可能差五倍。

风险与置信度(Risk vs Confidence)

这是两个独立的数字,永远不要合并成一个:

维度 回答的问题 高值意味着
风险 如果真坏了,有多严重? 需要优先处理
置信度 静态分析有多确定? 结论可信,可直接采信

最需要人工介入的组合是高风险 + 低置信度:可能很严重,但工具没把握。 此时正确做法是人工确认,而不是当成”确定受影响”或”确定没事”。

反例:一个 public 方法被删除,风险很高(调用方会编译失败), 但如果调用方是反射调用的,静态分析找不到它——置信度很低。 两个数字分开显示,才让这种情形可被识别。

一次分析的完整链路

① 取两个版本快照(base / head)
② 索引两版代码 → 各自的代码知识图谱
③ 比对图谱 → 语义变更清单(不是文本 diff)
④ 每个变更 → 找出它触及的契约
⑤ 对每个被选中的其他程序 → 找出契约使用点
⑥ 在使用点所在的图里反向传播
⑦ 打分:风险 + 置信度,并生成可读原因

下一步