评分模型
为什么是两个数字
风险(Risk)和置信度(Confidence)回答不同的问题:
- 风险:如果这个影响是真的,后果有多严重?
- 置信度:静态分析有多大把握认为这个影响存在?
合并成一个分数会丢掉关键信息。考虑两种情形:
| 情形 | 风险 | 置信度 | 正确处置 |
|---|---|---|---|
| 删除 public 方法,调用方清晰可见 | 高 | 高 | 立刻修,影响明确 |
| 删除 public 方法,调用方可能来自反射 | 高 | 低 | 需要人工确认,不能假定没事 |
| 改了内部实现细节,只有一个日志调用方 | 低 | 高 | 可延后 |
| 配置项改了,读取方位置不明 | 中 | 低 | 需要确认配置是否生效 |
第三种和第四种如果用单一分数,可能落在同一个值——但它们需要的动作完全不同。
风险公式
R = 100 × (0.25·S + 0.20·D + 0.20·B + 0.20·C + 0.15·U)
S 变更本身的风险(changeRisk) ← 来自变更类型的种子值
D 传播深度衰减(depth) ← 越远越弱
B 行为变化可能性(behavior) ← 影响类型 × 用法权重
C 影响对象重要程度(criticality) ← 调用方数量 + 是否公开 API
U 分析不确定性(uncertainty) ← 1 - 置信度
等级划分:
| 等级 | 分数区间 |
|---|---|
CRITICAL |
≥ 80 |
HIGH |
≥ 60 |
MEDIUM |
≥ 40 |
LOW |
≥ 20 |
INFO |
< 20 |
各因子怎么算
S — 变更风险:直接取变更类型的种子值(见 变更识别规则)。
D — 深度衰减:max(0.15, 1.0 - (depth-1) × 0.15)。
深度 1 是 1.0,深度 2 是 0.85,深度 5 是 0.4,到深度 7 之后触底 0.15。
越远的影响越不可靠,这是合理的先验。
B — 行为变化可能性:
B = 影响类型权重 × (0.4 + 0.6 × 用法权重)
影响类型权重:SECURITY 1.0 / BEHAVIOR 0.9 / COMPILE 0.85 / API_CONTRACT 0.85 /
DATA 0.8 / CONFIG 0.65 / TYPE 0.6。
用法权重是关键修正:
| 对方怎么用这个返回值 | 权重 |
|---|---|
参与分支条件(CONDITION) |
1.0 |
直接返回(RETURN) |
0.9 |
赋值给变量(ASSIGNMENT) |
0.8 |
作为实参(ARGUMENT) |
0.7 |
赋值但没人用(IGNORED) |
0.45 |
只打日志(LOG_ONLY) |
0.2 |
这解释了报告里最常见的一个现象:同一个方法改动,不同调用方的风险差好几倍。
C — 重要程度:0.35 + min(0.5, 调用方数量 × 0.05) + (公开 API ? 0.15 : 0)。
调用方越多越重要,公开 API 额外加分。
U — 不确定性:1 - 置信度。
置信度怎么算
置信度是沿路径连乘衰减的结果:
confidence(起点) = 1.0
confidence(下一跳) = confidence(当前) × 边系数 × 0.82
边系数按关系类型区分(只衡量链接可靠度,不含用法强度):
| 关系 | 系数 |
|---|---|
CALLS |
基础置信度 |
CALLS_API |
× 0.95 |
REFERENCES_TYPE |
× 0.85 |
IMPLEMENTS / EXTENDS |
× 0.9 |
READS_TABLE / WRITES_TABLE |
× 0.75 |
USES_CONFIG |
× 0.85 |
TESTS |
0(测试不参与传播) |
基础置信度来自解析质量:单一候选的调用 0.85,有歧义的多候选 0.6,动态分派更低。
置信度低于 0.15 的路径会被剪掉——再传下去也没有信息量。
等级:HIGH ≥ 0.8、MEDIUM ≥ 0.55、LOW < 0.55。
一个完整例子
变更:UserService.isActive 的分支条件改了
S = 0.80(METHOD_CONDITION_CHANGED)
命中:OrderService.createOrder 调用它,返回值参与 if 判断
depth = 1 → D = 1.00
impactType = BEHAVIOR → 类型权重 0.9
usage = CONDITION → 用法权重 1.0
B = 0.9 × (0.4 + 0.6 × 1.0) = 0.90
C = 0.35 + min(0.5, 3×0.05) + 0 = 0.50
confidence = 0.85 → U = 0.15
R = 100 × (0.25×0.80 + 0.20×1.00 + 0.20×0.90 + 0.20×0.50 + 0.15×0.15)
= 100 × (0.20 + 0.20 + 0.18 + 0.10 + 0.0225)
= 70.25 → HIGH
同样的改动,如果调用方只打日志(usage = LOG_ONLY,权重 0.2):
B = 0.9 × (0.4 + 0.12) = 0.468,总分降到约 61——从 HIGH 边缘落到 MEDIUM。
可调参数
code-association:
max-depth: 8 # 传播最大深度,同时也是 D 因子的下限来源
其余权重固化在 RiskScorer 与 PropagationRules 中,集中在一处便于调整。