Reproduce the smallest failure
A report says an average is too small. The data is [10, 20]. Expected average is 15, actual is 10. Resist changing the data until the formula's behavior is understood.
const values = [10, 20];
const sum = values.reduce((total, value) => total + value, 0);
const incorrectAverage = sum / (values.length + 1);
const average = sum / values.length;
console.assert(sum === 30);
console.assert(incorrectAverage === 10);
console.assert(average === 15);
The sum is correct. The denominator counts an extra item. Inspecting intermediate values isolates the decision that diverges from the rule.
A repeatable process
- Reproduce the behavior with known input.
- Record expected and actual results.
- Locate the smallest area that could explain the difference.
- Inspect relevant values.
- State a hypothesis before editing.
- Change or observe one thing to test it.
- Correct the demonstrated cause.
- Retest the original case and nearby cases.
A hypothesis should predict something observable. "JavaScript is broken" is not useful here; "the count is one too large" predicts the denominator you should see.
Independent exercise
A maximum-finding routine starts maximum at 0, then processes [-5, -2]. It returns 0. Explain the cause, propose a correction and choose a case that checks the correction without merely repeating this input.
Correction
Zero was invented as a candidate although it was not in the data. Initialize from the first actual value after checking that the array is nonempty, or use a null no-result state. Verify [-5, -2] gives -2, [4] gives 4 and [] gives the explicitly agreed no-result value. Do not discard negatives just to make the original algorithm pass.
Review
Keep the failing case as a regression check: it should continue to pass after later changes. Debugging ends with evidence that the cause is fixed, not merely with the disappearance of one visible symptom.