Turn "another round of changes" into inspectable progress: which explanation was confirmed or ruled out, why the patch fixes the cause, and which behaviors have been retested. The method is based on Andreas Zeller's Introduction to Debugging full chapter; for reading scope and attribution, see source note. You do not need to install QBS or download the original book first to use it.
Establish a baseline from the failure
Read the relevant code, existing tests, and the reproduction materials provided by the user. Determine the basis for expected behavior, record the actual behavior, triggering input, environment, and rerunnable command; preferably write the original failure as a test and keep a relevant successful control.
When you cannot reproduce it, first check for differences in version, input, or environment, and output the observed facts and the next piece of evidence most likely to distinguish the cause. When the expected behavior is unclear, clarify it first; do not declare the code wrong based on a specification you guessed yourself. For intermittent issues, retain the conditions and frequency of occurrence; do not declare it fixed because it failed to fail once.
Use experiments to change your judgment
- Propose explanations based on the difference between failure and success. When there are plausible competing explanations, choose inputs, breakpoints, or local assertions that can distinguish them; do not assume there is only one common root cause merely because several entry points fail.
- Write a prediction before the experiment: if the explanation holds, what will be seen; if not, which part will be refuted or weakened. Distinguish the product's correct expectations from the hypothesis's prediction about the faulty behavior.
- After actually running it, record the observations, then update your judgment. Temporary instrumentation should target one judgment and avoid dumping logs aimlessly; keep diagnostic changes separate from the final fix. Write experiments that were not run as pending; do not fabricate results.
- New hypotheses must be compatible with existing observations. For explanations that have been ruled out, retry only when new evidence appears or conditions change. You can use debugging notes; simple errors can be compressed into a few sentences, with no requirement to fill out forms, pad the number of hypotheses, or add experiment rounds.
Diagnosis and fix
Before the final fix, explain two things:
- Causality: how does the defect make state or control flow go wrong and propagate to the failure the user sees? Support it with experiments, execution traces, or direct code evidence.
- Wrongness: which confirmed behavioral constraint does the code violate? Why does this change cover the relevant inputs, rather than merely adding a special case for the current failing value?
Keep symptoms that cannot be explained separately. If evidence is insufficient, deliver the current diagnostic state and the next experiment; do not treat a confident tone as evidence of root cause. When evidence is sufficient and the task has authorized a fix, make a focused patch directly; do not add a separate "approve diagnosis" step. Submitting, publishing, or closing external issues follows the current task authorization; the book's closing suggestions do not expand permissions.
Rerun the original failure, the relevant original successes, and boundary tests related to the modified logic. If the original failure still exists, return to diagnosis; do not pass by loosening assertions. Check for similar errors according to impact scope, add regression tests, and remove temporary probes; retain constraint assertions or explanatory comments only when they help prevent recurrence.
Delivery and acceptance
Deliver the fix artifact (if authorized and completed) and a brief diagnostic record:
- reproduction command, original failure, and basis for expectation;
- Predictions, actual observations, and explanations supported or ruled out in valid experiments;
- Causal chains, violated constraints, and patch locations;
- Actual commands run and pass/fail/not-run results, remaining unexplained symptoms and limitations.
Acceptance depends on whether others can reproduce the key judgments, and whether the fix eliminates the original failure while preserving related correct behavior. A complete format, well-written test files, or passing static checks do not equal completed runtime verification.
Finally, leave a lightweight reading entry point: point outactually used this timemethods and links to the original chapter sections, then leave a question. For example, if this time an intuitive explanation was ruled out, you can link to Testing a Hypothesis, and ask, "Which observation truly made us abandon our initial guess?" Reading is an extension after using the methods.