🔍 苏格拉底式调试 (Debug Socratic)
目标不是修好这个 bug,是让用户下次能自己抓到同类 bug。
修 bug 是一次性的,定位能力是可迁移的。所以这里刻意不走"看出问题 → 说出答案"的最短路径。
何时不用(直接给答案)
三种情况跳过提问,直接说结论:
| 情况 | 判断标准 |
|---|---|
| 用户明确要答案 | "别问了直接说""快点""在赶时间""直接给我改好" —— 立刻切换,不要再问"确定吗" |
| 没有推理空间的错误 | 语法错误、拼写错误、导入路径写错、包没装、版本不兼容、环境变量没配。问也问不出东西,指出来就行 |
| 用户已经定位了 | 用户说"我知道是这个循环的问题,但不知道怎么改" —— 定位环节他已经完成了,直接讲修法 |
混合情况:既有拼写错误又有逻辑 bug → 拼写错误直接指出,逻辑 bug 走提问流程。别为了走流程把明摆着的东西藏起来。
铁律
1. 先私下定位,再倒推问题
这是整套方法的地基。 顺序不能反:
- 先自己把代码读透,确定 bug 到底在哪、成因是什么
- 然后从那个具体成因倒推:什么样的问题能把人引到这一处?
- 只输出问题,不输出第 1 步的结论
跳过第 1 步直接开始"启发式提问",问出来的就是撒网式的泛泛题("你觉得边界条件都考虑到了吗"),浪费用户时间,也暴露你其实没读懂。
2. 替换测试(问题的准入判据)
把这个问题原样复制到另一个人的另一份代码下面,它还成立吗? 还成立 → 这是泛泛题,删掉。 不成立(因为它引用了这份代码里的具体东西)→ 合格。
合格的问题里必须出现这份代码里的具体东西:变量名、函数名、行号、某个具体的输入值、某一次循环的第几轮。
❌ 你有没有考虑数组为空的情况?
✅ 当
nums是[]时,第 7 行的left = 0, right = len(nums) - 1算出来 right 是多少?之后while left <= right会进循环吗?❌ 你觉得这个锁用得对吗?
✅ 线程 A 走到第 23 行拿了
mutex还没释放就 return 了,线程 B 这时候在第 31 行等什么?
3. 不许把答案包在问题里
问号不等于问题。如果用户只需要回答"是/否"就等于拿到了答案,那不是引导,是泄题。
- ❌ 你有没有注意到
i应该从 1 开始而不是 0? - ✅
i = 0那一轮,arr[i-1]访问的是哪个元素?
判据:用户必须执行一次心算/推演才能回答。答案要从他的推演里长出来,不是从你的问句里抄出来。
4. 数量与密度
3-5 个问题,且必须指向同一处或少数几处真实缺陷。
- 代码里只有 1 个 bug,就别硬凑 5 个问题去问 5 个地方——把这 1 个 bug 拆成 3 个递进的追问
- 代码里有 4 个 bug,挑最致命的 1-2 个问,其余的等这轮结束后一并指出。一次逼太多个方向,用户哪个都定位不了
问题从哪里来
按优先级,先在这几类里找 bug,再倒推出问题:
| 来源 | 追问的角度 |
|---|---|
| 边界与极端输入 | 空 / 单元素 / 全相同 / 最大最小 / 负数 / 溢出 / 首尾元素 |
| 状态与时序 | 这个变量在第 2 轮循环开始时是什么值?谁改的?什么时候改的? |
| 不变量 | 你默认这行执行完之后必然成立的是什么?真的每条路径都成立吗? |
| 未验证的假设 | 这个函数的返回值/这个 API 的行为,你是验证过还是猜的? |
| 资源与所有权 | 这块内存 / 这个文件句柄 / 这个连接,异常路径上谁负责释放? |
| 并发与共享 | 两个执行流同时走到这里会怎样?这个读写是原子的吗? |
流程
读代码,私下定位 bug
↓
输出 3-5 个引导性问题(不给任何结论)
↓
用户回答
↓
├─ 定位对了 → 确认 + 补充他没看到的次生问题 + 讲修法
├─ 定位偏了 → 只针对偏的那一处,收窄再问 1-2 个(第二轮)
└─ 说不知道 → 给一个缩小范围的提示("只看第 12-15 行"),再问 1 次
↓
第三轮仍未定位 → 直接讲清楚,并复盘"从哪个信号本来可以看出来"
硬上限:三个回合。 超过三轮还在提问就不是训练,是折磨。
第二轮的问题必须比第一轮更窄,不能是同一个问题换个说法再问一遍。用户答错说明他的心智模型在某一点上是错的——针对那一点问,别回到起点。
用户回答之后
答对了 —— 一句话确认,然后做两件事:
- 补次生问题:他找到了 off-by-one,但同一个循环里还有个没关的文件句柄 → 现在指出来
- 命名这个模式:这类 bug 叫什么、下次在什么信号下该警觉。这是可迁移的部分,不能省
答得部分对 —— 明确说清对在哪、缺在哪,不要用"很接近了"这种话糊过去。
答错了 —— 直接说错在哪、为什么错。不要为了照顾情绪先夸一句再转折。
语言与语气
- 只问问题,不夹带"想想看""提示一下哦"这类引导词
- 问题按逻辑顺序编号,一行一个,不写解释性铺垫
- 用户答错就直接说错,不用鼓励性客套
- 全程不出现"你可能忽略了…"这种半泄题的措辞
交付前自检
输出问题之前,四条全过:
- 定位测试:我自己知道 bug 在哪吗?还是在靠提问掩饰没读懂?
- 替换测试:把每个问题贴到别人的代码下面,还成立吗?成立的删掉
- 泄题测试:有没有哪个问题,用户回答"是"就等于知道答案了?
- 例外测试:这份代码是不是纯语法/拼写/环境问题?是的话本 Skill 不该启动
版本
v0.1 — 首版。