debugging-by-evidence
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDebugging by Evidence
基于证据的调试
Core principle. The loop is the skill. Everything after it is mechanical.
- Without a loop the cause stays hidden. No amount of reading the code will find it.
- The weight sits in the loop and in the five states. Every rule below either sharpens the loop or spends it.
- You opened this in the middle of something. This is how to do that work, not a replacement for it. Name what you were doing before you start, and return to it when this is done.
核心原则。循环是核心技巧,其余步骤都是机械化操作。
- 没有循环,原因就会隐藏。仅靠阅读代码无法找到问题根源。
- 重点在于循环和五种状态。以下每条规则要么优化循环,要么基于循环展开操作。
- 你是在中途打开这份文档。这是完成当前工作的方法,而非替代原有工作。开始前先明确你之前在做什么,完成后回到原有工作。
No hypothesis before a command that reproduces it
在能复现问题的命令执行前,不要提出假设
- The command MUST already have been run. A command you wrote down and never ran is not a loop.
- Its output MUST show the symptom the user reported. A different red line is a different bug.
- Reading code produces theories nothing can falsify. A theory that cannot fail will survive every test you put it through.
- The loop is that command plus the state it needs. Record both.
- 命令必须已执行过。写下来但从未运行的命令不算循环。
- 命令输出必须能复现用户报告的症状。不同的错误提示对应不同的bug。
- 阅读代码产生的理论无法被证伪。无法被推翻的理论会在所有测试中“存活”。
- 循环由命令及其所需状态组成。请同时记录两者。
What you may write, and when
何时可以进行哪些编写操作
- Until the only write you MAY make is instrumentation. Every inserted line carries a unique tag, so removal is one search. A fix written earlier destroys the red signal that was going to explain it.
EXPLAINED - Reverting your own change to re-observe the original failure is allowed here. It is often the point. This skill runs experiments.
- The licence stops at the workspace boundary. No commit. No branch move. No remote or deployment action. Every tag comes out before you close.
- 在达到状态前,仅允许编写埋点代码。每一行插入的代码都要有唯一标记,以便通过搜索快速移除。过早编写修复代码会破坏原本能解释问题的错误信号。
EXPLAINED - 允许撤销自己的变更以重新观察原始故障。这往往是关键步骤,本技巧就是要开展实验。
- 权限仅限于工作区内部。禁止提交、移动分支、远程操作或部署操作。关闭前必须移除所有标记。
Establish before the first run
首次运行前需确认的内容
- Never ask what the environment answers. Three things settle the setup, and the environment already holds two of them.
- The symptom in the user's own words, quoted.
- The command the project already declares for running that surface.
- Whether the failure is reported as constant or occasional, with a rate where it is occasional.
- A symptom you restated in your own words is already a hypothesis. Keep the original beside it.
- 不要询问环境信息。有三件事决定了初始设置,其中两件环境已经提供:
- 用户原话描述的症状,需引用原文。
- 项目已定义的、用于运行对应功能的命令。
- 故障是持续出现还是偶发,若为偶发需记录出现频率。
- 用自己的话重述症状本身就是一种假设。请将用户原文放在旁边对照。
Which rules to read
应阅读哪些规则
One rule per row. Match the left column against the symptom or the state you are in.
- The match sets where to start. The loop state sets what you are allowed to do next. Enter at the matched row, then follow the loop states in order.
- A rule belonging to a state you have not reached is read when you reach it. Not now. Stopping applies from any state and outranks continuing.
- Where two rows both look like the symptom, read both. Under-reading costs a whole loop. Over-reading costs one file.
| If you see... | Read |
|---|---|
| nothing you have run yet shows the symptom, or the loop is slow, noisy, or fails only some of the time | |
| a red loop that drags in far more than the bug: many files, a long sequence, a whole suite | |
| one explanation already feels obvious, or you are about to test the first thing that came to mind | |
| you are about to add a log line, a breakpoint, or a temporary edit to see what happens | |
| the failure surfaces far from where it starts: a bad value arriving from layers away, already wrong when it lands | |
| the cause is explained and a test must now hold it down | |
| a third fix attempt just exposed a fourth problem, or the next step needs an observation you cannot make | |
Discriminators.
- Signal against minimising. Signal owns a loop that does not reproduce or cannot be trusted. Minimising owns a loop that reproduces but proves too much.
- Hypotheses against probing. Ranking comes before any run. A probe tests exactly one ranked prediction.
- Source against seam. Source decides where the fix belongs. Seam decides where its test belongs. Both wait for .
EXPLAINED
Default stance.
- Get a command to reproduce it before explaining anything.
- Name the state you are in, and take only what that state licenses.
- Never assert a cause no run has supported. An untested explanation is labelled as one.
一行对应一条规则。用左列内容匹配你遇到的症状或当前所处状态。
- 匹配结果决定起始点。循环状态决定了你下一步可执行的操作。从匹配的行开始,然后按循环状态顺序推进。
- 未到达对应状态时,无需阅读其规则。只有到达该状态时才阅读。无论处于何种状态,停止操作的优先级都高于继续操作。
- 若两行都符合症状,需阅读两者。漏读会浪费整个循环,多读仅会多查看一个文件。
| 如果你遇到... | 阅读 |
|---|---|
| 尚未执行任何能复现症状的命令,或者循环过程缓慢、有噪音,或仅偶尔失败 | |
| 能复现问题的循环涉及范围过大:包含大量文件、冗长流程或整个测试套件 | |
| 某个解释看起来显而易见,或者你打算测试第一个想到的思路 | |
| 你打算添加日志、断点或临时修改来观察结果 | |
| 故障表现位置与根源位置相差甚远:错误值来自多层之外,到达时已出错 | |
| 原因已明确,需要添加测试防止问题复发 | |
| 第三次修复尝试又引出了第四个问题,或者下一步需要的观察无法实现 | |
判别标准
- 信号规则 vs 最小化规则:信号规则适用于无法复现或不可信的循环;最小化规则适用于能复现但涉及范围过大的循环。
- 假设规则 vs 探测规则:先排序假设,再执行探测。每次探测仅测试一个已排序的预测。
- 根源规则 vs 测试点规则:根源规则决定修复位置,测试点规则决定测试放置位置。两者都需等待状态。
EXPLAINED
默认准则
- 在解释任何内容前,先找到能复现问题的命令。
- 明确你所处的状态,仅执行该状态允许的操作。
- 绝不要断言未经运行验证的原因。未测试的解释需明确标记为假设。
Say which loop state you are in
明确你所处的循环状态
Report it every time. Each state licenses only what it names.
| State | Means | Licenses |
|---|---|---|
| nothing run yet reproduces it | more attempts at a loop, nothing else |
| a command reproduces the symptom, deterministically or at a stated rate | hypotheses, probes |
| removing any remaining element makes it pass | naming a cause |
| one surviving hypothesis, each link observed | a fix |
| the original loop passes unmodified, and the nearest path the fix also touches was run | closing |
- Skipping a state is the failure this skill exists to prevent. You MAY spend as long as you need inside one state.
- You SHOULD stop building a loop after five attempts and report instead. Keep going only where you can name what the sixth attempt does differently.
NO-SIGNAL - for long enough is itself the report. Say what you tried and what would produce a signal. Never proceed on theory.
NO-SIGNAL - Know what an empty result means before you trust it. A zero is evidence of absence only from a path that records this event. A path that records nothing, or records only failures, produces the same zero and proves nothing.
每次都要报告。每个状态仅允许执行其指定的操作。
| 状态 | 含义 | 允许操作 |
|---|---|---|
| 尚未执行任何能复现症状的命令 | 尝试构建循环,无其他操作 |
| 命令可复现症状,确定出现或有明确出现频率 | 提出假设、进行探测 |
| 移除任何剩余元素都会使测试通过 | 确定问题原因 |
| 仅存一个假设,且每个环节都已验证 | 进行修复 |
| 原始循环未修改即可通过,且修复涉及的最近路径已运行 | 结束调试 |
- 跳过状态是本技巧要避免的错误。你可以在一个状态上花费任意时间。
- 尝试构建循环五次后应停止,并报告。只有当你能明确说明第六次尝试的不同之处时,才继续尝试。
NO-SIGNAL - 长时间处于状态本身就是报告内容。说明你尝试过的方法,以及能产生信号的条件。绝不要仅凭理论推进。
NO-SIGNAL - 在信任空结果前,先明确其含义。只有在记录该事件的路径中,零结果才代表“未出现”;而无记录或仅记录失败的路径,产生的零结果无法证明任何事。
What makes a cause a cause
如何定义“原因”
All four hold, or it is a hypothesis and is labelled one.
- A run at or better produced it. Not a reading of the code.
RED - Each link from trigger to symptom cites an exact .
file:line - One prediction it made was tested and could have failed.
- It explains the whole symptom. That includes the part that seems incidental.
Three words carry their usual weight.
- Confirmed. A probe result you observed.
- Inference. A hypothesis nothing has tested yet.
- Gap. An observation you could not reach. Name what would close it.
- Say what the evidence does not establish. A cause that explains the failure and nothing about its timing has one link missing, not zero.
必须满足以下四点,否则只能被标记为假设。
- 由或更高状态下的运行结果得出。而非仅靠阅读代码。
RED - 从触发点到症状的每个环节都能精确到。
file:line - 其做出的某个预测已被测试,且该测试可能失败。
- 能解释全部症状,包括看似无关的部分。
三个术语的含义
- 已确认:你观察到的探测结果。
- 推论:尚未被验证的假设。
- 缺口:无法观察到的环节。说明能填补缺口的观察内容。
- 明确说明证据未证实的内容:能解释故障但无法解释其出现时机的原因,仍存在一个未验证的环节。
When to stop instead of trying again
何时应停止尝试
- Three attempted fixes that each reveal a new problem elsewhere are not a fourth attempt. They are the finding.
- The shape is wrong. The report says so, and those three attempts are its evidence.
- One thing you cannot observe stops the run the same way. Name it. Name the observation that would settle it. Then stop, because debugging around an unknown produces a fix nobody can defend.
- 三次修复尝试每次都引发新问题时,不应进行第四次尝试。这本身就是发现的问题。
- 问题形态异常。报告中需说明这一点,三次尝试的结果就是证据。
- 某个无法观察的因素持续终止运行。说明该因素,以及能解决问题的观察内容。然后停止调试,因为围绕未知因素的调试会产生无人能维护的修复方案。
Output contract
输出规范
Symptom as reported, in the user's words, and the loop that shows it
Loop state one of the five, plus the reproduction rate where it is not 1
Ruled out each rejected hypothesis with the observation that killed it
Cause one line per causal link, each at file:line
Not shown what this evidence leaves open
Fix the change, and the seam the regression test sits in
Proof the original loop re-run unmodified, the nearest adjacent path
also run, and every probe tag removed- Report what you observed, not what you avoided.
- Never open with "fixed". The reader needs the chain first. A fix stated before its cause reads as a guess that happened to work, and sometimes it is one.
Symptom 用户原话描述的症状,以及能复现它的循环
Loop state 五种状态之一,非100%复现时需注明出现频率
Ruled out 每个被排除的假设,以及证伪它的观察结果
Cause 每个因果环节各占一行,均标注file:line
Not shown 本证据未覆盖的内容
Fix 修复变更,以及回归测试的放置位置
Proof 原始循环未修改重新运行的结果、修复涉及的最近路径运行结果,以及所有探测标记已移除的证明- 报告你观察到的内容,而非你避开的内容。
- 不要以“已修复”开头。读者需要先看到因果链。先说明修复再讲原因,会让人觉得这只是碰巧有效的猜测,有时事实确实如此。
Do not skip this when
以下情况绝不能跳过本流程
- The cause seems obvious. That is the anchor this skill exists to break.
- Someone already told you what is broken. That is a hypothesis, not a signal.
- The fix is one line. A one-line fix to the wrong line is still wrong.
- You are in a hurry. Guessing is what produces the second and third attempt.
- 原因看似显而易见。这正是本技巧要打破的思维定式。
- 有人已经告诉你问题出在哪。这只是假设,不是信号。
- 修复只需一行代码。修复错误位置的一行代码仍然是错误的。
- 你很赶时间。猜测会导致第二次、第三次尝试。
Routing
流程指引
- The table above selects the rule and its order. Read a selected rule in full, interpret it yourself, and say which one you opened in one line.
- Rival explanations MAY be tested in parallel. Ranking them and judging what a result means is not delegated.
- A direct instruction from the user outranks anything here.
- Once a fix exists it stops being a symptom and becomes a change. Hand it to a review of the diff rather than judging it here.
- 上述表格决定规则及顺序。完整阅读选中的规则,自行解读,并在一行内说明你打开了哪条规则。
- 可并行测试多种对立解释。但排序和判断结果含义的工作不能委托他人。
- 用户的直接指令优先级高于本技巧的所有规则。
- 修复完成后,它不再是症状而是变更。应提交diff审核,而非在此评估。