---
name: Systematic Debugging
version: 1.0.0
description: 包含根因分析的四阶段调试方法论。在调查Bug、修复测试失败或排除异常行为时使用。在找到根因之前绝不动手修复。
---

# 系统化调试 (Systematic Debugging)

## 核心原则

**在未完成根因调查之前，绝不动手修复。**

永远不要应用只针对症状的补丁，因为那会掩盖潜在问题。在尝试修复之前，必须理解失败的**原因（为什么？）**。

## 四阶段框架

### 第一阶段：根因调查 (Root Cause Investigation)

在改动任何代码之前：

1. **彻底阅读错误信息** - 每一个字都至关重要。
2. **稳定重现问题** - 如果无法重现，就无法验证修复。
3. **检查最近的变更** - 在问题开始出现之前，有哪些改动？
4. **收集诊断证据** - 日志、堆栈追踪、状态转储（State Dumps）。
5. **追踪数据流** - 顺着调用链找到异常值源于何处。

**根因追踪规范：**
> 1. 观察症状 - 错误在哪里显现？
> 2. 寻找直接原因 - 哪行代码直接产生了错误？
> 3. 询问“谁调用了它？” - 向上映射调用链。
> 4. 持续向上追踪 - 在堆栈中向后追踪无效数据。
> 5. 寻找原始触发点 - 问题究竟是从哪里开始的？

**关键原则：** 永远不要只在错误出现的地方修复问题——务必追踪到原始触发点。

### 第二阶段：模式分析 (Pattern Analysis)

1. **寻找正常运行的案例** - 找到实现逻辑相似但运行正确的代码。
2. **完整对比实现** - 表面和内在都要，不要走马观花。
3. **识别差异点** - 运行正常与运行失败的代码之间有什么不同？
4. **理解依赖关系** - 这段代码依赖于哪些外部因素？

### 第三阶段：假设与测试 (Hypothesis and Testing)

应用科学方法：

1. **制定一个明确的假设** - “错误发生是因为 X ”。
2. **设计最小化测试** - 一次只改变一个变量。
3. **预测结果** - 如果假设正确，应该发生什么？
4. **执行测试** - 运行并观察。
5. **验证结果** - 行为是否符合预测？
6. **迭代或继续** - 如果错误，修正假设；如果正确，开始实施。

### 第四阶段：实施修复 (Implementation)

1. **创建失败的测试用例** - 捕获 Bug 的行为。
2. **实施单一修复** - 针对根因，而非症状。
3. **验证测试通过** - 确认修复有效。
4. **运行全量测试套件** - 确保没有引入回归错误。
5. **如果修复失败，立即停止** - 重新评估假设。

**关键规则：** 如果连续三次尝试修复均告失败，**停止**。这预示着存在架构性问题，需要讨论而非更多补丁。

## 红灯警告 - 违规行为

如果你发现自己产生以下想法，请立即停止：

- “先快速修复，以后再查。”
- “再试一种修复方法。”（在多次失败后）
- “这应该能行。”（在不理解原理的情况下）
- “让我尝试一下……”（在没有假设的情况下）
- “在我的机器上是好的。”（在未调查差异原因的情况下）

## 深度问题的预兆

**连续的修复在不同区域引发了新问题**，这表明存在架构缺陷：

- 停止打补丁。
- 记录已发现的情况。
- 在继续之前与团队讨论。
- 考虑是否需要重新思考设计。

## 常见调试场景

### 测试失败
1. 阅读完整的错误信息和堆栈追踪。
2. 识别哪个断言失败了以及原因。
3. 检查测试设置 - 测试环境是否正确？
4. 检查测试数据 - Mocks/Fixtures 是否正确？
5. 追踪到预期外数值的来源。

### 运行时错误 (Runtime Errors)
1. 获取完整的堆栈追踪。
2. 准确定位抛出异常的代码行。
3. 检查哪些值是 undefined 或 null。
4. 向后追踪以找到坏值产生的源头。
5. 在源头添加校验逻辑。

### “以前是好的”
1. 找到引入错误的提交，即最后一次修改了什么。
2. 将变更与之前的正常版本进行对比。
3. 识别哪些假设发生了变化。
4. 在违反假设的源头进行修复。

### 间歇性失败
1. 寻找竞争条件（Race Conditions）。
2. 检查共享的可变状态。
3. 检查异步操作的顺序。
4. 寻找时序依赖。
5. 添加确定性的等待或正确的同步机制。

## 调试检查表

在声称 Bug 已修复之前：

- [ ] 已识别并记录根因
- [ ] 已制定并测试假设
- [ ] 修复针对的是根因，而非症状
- [ ] 已创建能重现 Bug 的失败测试用例
- [ ] 应用修复后，测试现在通过
- [ ] 全量测试套件通过
- [ ] 未使用“快速修复”等借口
- [ ] 修复方案精简且专注

## 成功指标

系统化调试的首跳修复率约为 **95%**，而随意调试的方法仅为 **40%**。

做对的迹象：
- 修复没有产生新 Bug。
- 你能解释 Bug 发生的**原因**。
- 同类 Bug 不再重复出现。
- 代码在修复后变得更健壮，而不仅仅是“能运行”。

## 与其他技能结合

- **测试模式（testing-patterns）**：在修复之前，先创建能够重现该 Bug 的测试。
