五、调试不再盲目:系统化调试的思维转变

4 阅读4分钟

遇到bug时,传统的方式是:看到症状→猜测原因→改代码→试试。改对了也不知道为什么,改错了继续猜测。

Superpowers的Systematic Debugging技能提供不同的方法:从症状到根因的证据链。

系统化调试的四阶段

  1. Observe:收集信息,不猜测
  2. Hypothesize:基于观察提出假设,每个假设有验证方法
  3. Isolate:控制变量验证,缩小范围
  4. Fix:基于确定根因修复,写测试验证

每一步都有明确的检查点。不是"试试看",是"验证假设"。

Observe阶段:收集而非猜测

传统方式的Observe是:"看起来像是异步问题"、"可能是数据库连接"、"感觉是缓存没更新"。

这些不是观察,是猜测。真正的观察是收集事实:

  • 错误消息的完整内容
  • 日志中的异常
  • 复现的条件:什么操作导致问题?
  • 问题的频率:总是发生?偶尔发生?
  • 问题的时间模式:什么时候开始?什么时间点触发?

AI在这一阶段会:

  • 读取错误日志
  • 搜索相关代码文件
  • 收集复现步骤

AI报告的是事实,不是解释。比如:

Observe findings:
- Error message: "Cannot read property 'id' of undefined"
- Stack trace: line 45 in todoStore.js, in deleteTodo function
- Reproduction: delete a task that doesn't exist
- Frequency: always when deleting non-existent task
- Log output: no relevant log before error

这是事实。没有"看起来像是...",没有"可能是因为..."。

Hypothesize阶段:假设附带验证方法

基于观察,提出可能的原因。但每个假设必须有验证方法:

Hypotheses:

H1: deleteTodo doesn't check if task exists before accessing task.id
   Verification: Add console.log before line 45 to see if task is undefined

H2: The task ID parameter is wrong type (string vs number)
   Verification: Log the type of id parameter

H3: The tasks array is corrupted
   Verification: Log tasks array before delete operation

这不是"试试改H1",是"验证H1是否成立"。先验证,再决定修复方向。

Isolate阶段:控制变量验证

逐一验证假设:

Testing H1:
Added console.log before line 45.
Result: task is undefined when deleting non-existent task.
H1 confirmed: deleteTodo accesses task.id without checking existence.

Testing H2:
Logged id parameter type.
Result: id is always number.
H2 rejected: type is not the issue.

Testing H3:
Logged tasks array.
Result: tasks array correct.
H3 rejected: array not corrupted.

确定根因:H1成立。deleteTodo假设task总是存在,没有处理不存在的情况。

Fix阶段:基于根因修复

现在知道根因,修复有明确方向:

// Before
function deleteTodo(id) {
  const task = tasks.find(t => t.id === id);
  tasks.splice(tasks.indexOf(task), 1);  // task may be undefined
}

// After
function deleteTodo(id) {
  const task = tasks.find(t => t.id === id);
  if (!task) {
    return null;  // or throw error, depending on spec
  }
  tasks.splice(tasks.indexOf(task), 1);
  return task;
}

但Superpowers要求:修复必须写测试验证。

测试验证

test('deleteTodo returns null for non-existent task', () => {
  const result = deleteTodo(999);
  expect(result).toBeNull();
});

RED → GREEN循环:写测试,看失败,修复,看通过。

Defense-in-Depth:修复后的防御

修复后不是结束。Superpowers要求添加防御措施:

Defense-in-Depth measures:
1. Add validation at API level: DELETE /todos/:id returns 404 if task not found
2. Add test for 404 response
3. Consider: should other operations also check existence? (GET, PUT)

这不是"额外工作",是防止类似问题的必要步骤。

为什么系统化调试更有效

对比时间:

传统猜测式

  • 第1次猜测:加setTimeout → 好了?不确定
  • 第2次猜测:改顺序 → 好了?不确定
  • 第3次猜测:加缓存 → 好了?不确定
  • 问题复发:回到第1次
  • 时间:2天,不确定是否修复

系统化调试

  • Observe:30分钟
  • Hypothesize:15分钟
  • Isolate:1小时(验证)
  • Fix:30分钟(含TDD)
  • Defense:30分钟
  • 时间:3小时,确定修复

系统化调试更快,因为每一步有方向,不是盲目尝试。

AI在调试中的角色

AI擅长:

  • 收集信息(日志、grep、文件读取)
  • 控制变量的实验
  • 详细记录过程

AI需要你引导:

  • 用系统化方法(不是猜测)
  • 提供业务上下文(需求是什么)
  • 决策修复方向(多个选项选择哪个)

没有Superpowers,AI会和你一起猜测。有Superpowers,AI遵循系统化流程。

Red Flags:调试中的陷阱

Systematic Debugging技能有Red Flags:

- Jumping from symptom to fix directly
- "This looks like X" without evidence
- Changing multiple things at once
- "Let me try this" without hypothesis
- Fixing without test to verify
- No Defense-in-Depth after fix

如果AI意识到自己在做这些,它会停止,回到正确的阶段。

结论

系统化调试的本质是证据链:

症状 → 观察(事实) → 假设(可验证) → 验证(控制变量) → 根因 → 修复(有测试) → 防御

每一步都有证据,不是猜测。修复后知道为什么有效,不是"试试看好像好了"。

Superpowers强制AI遵循这个流程。AI不会迁就你的"快速修复"倾向。

下一步

下一篇《代码审查:让你的AI助手成为可靠的协作者》将展示Requesting Code Review技能:

  • 两阶段审查:Spec Compliance → Code Quality
  • 审查者如何独立验证
  • 审查循环:问题→修复→重新审查