Debugging: Reproduce, Inspect and Verify

Find why a total is one mark too high

A report totals marks 40 and 35 as 76 instead of 75. The loop appears reasonable, so changing random operators would risk introducing another mistake.

Debugging is a process of reproducing a failure, comparing intended and actual behavior, and narrowing the cause with evidence. A fix should address the cause and be rechecked against the original failure.

  1. Reproduce

    Write exact input and expected output.

  2. Inspect state

    Find the first point where execution differs from the model.

  3. Verify a fix

    Check the failing case and relevant boundaries.

Find the extra one before guessing

  1. Initialization

    The total is already wrong before any addition.

    1 instead of 0
  2. First addition

    The extra one remains visible.

    41 instead of 40
  3. Final result

    Both marks were added to the wrong initial value.

    76 instead of 75
Read these stages alongside the complete example. They explain the relationship; they do not execute code.

A small input gives a trace you can explain

Write the expected values before inspecting the implementation: zero initially, forty after the first mark, seventy-five after the second. Compare each transition rather than only the final output.

Logs can expose state, while a debugger breakpoint can pause and inspect local values and the call stack. Use either to test one hypothesis at a time. Do not change unrelated code merely because it is nearby.

Before starting, review running totals across iterations. These examples use JavaScript; other languages can use different syntax and rules.

Observe the faulty intermediate values

The program deliberately starts total at one. The first addition gives 41 and the second gives 76. That locates the divergence at initialization, not at the addition operator.

This is valid JavaScript with an incorrect rule for the intended sum. There is no thrown exception to catch.

JavaScript · local teaching example

const marks = [40, 35];
let total = 1;
for (const mark of marks) {
  total += mark;
  console.log(total);
}

Expected output

41
76

Change the cause and re-run the trace

Starting at zero removes the unexplained extra mark. The outputs now agree with the predicted intermediate state.

A correct result for one example is evidence, not proof for every input. Add a case that would expose the same initialization problem without additions.

JavaScript · local teaching example

const marks = [40, 35];
let total = 0;
for (const mark of marks) {
  total += mark;
  console.log(total);
}

Expected output

40
75

Apply the rule to a small change

Check the corrected rule on an empty array. Explain why this is a useful regression case.

Worked answer

The total should remain zero. The old implementation would have returned one even without marks, so this boundary directly exposes the original cause.

JavaScript · local teaching example

const marks = [];
let total = 0;
for (const mark of marks) total += mark;
console.log(total);

Expected output

0

Recognize mistakes and limits

A symptom may be downstream of a wrong input or an earlier mutation. Inspect where the first incorrect state appears rather than patching the final display.

Logs can leak private school data and alter timing in sensitive concurrent cases. Use minimal relevant evidence, remove temporary noise and preserve an automated regression check for the confirmed bug.

For the language or tool rules used here, see JavaScript errors and handling.

Check the core idea

JavaScript · code for this question

const marks = [40, 35];
let total = 1;
for (const mark of marks) {
  total += mark;
  console.log(total);
}
Where does the faulty total first differ from the intended sum?
Choose one answer. You can try again.

Answer and explanation

At initialization, before processing any marks.

Yes. total begins at one instead of zero.

Apply the idea to a new situation

Why test the empty array after the fix?
Choose one answer. You can try again.

Answer and explanation

It checks that the accumulator has the correct starting value without any additions.

Yes. It directly guards the identified cause.

Turn a confirmed cause into a repeatable check

Reproduce the failure, predict intermediate values, inspect the earliest divergence and fix its cause. Re-run the original case and a relevant boundary, then keep a regression test.

Connect this idea with failure categories and automated expectations.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Reading and Writing Files: Real Operations and Modes →