Mission control sends a friendly note. "Beacon says today's average water level is 30. The tomatoes look happy. Can you check?"
Comet pulls up the three readings: 30, 60 and 90. "The average should be 60," she says. "Beacon is wrong by a lot."
Comet winces. "I copied out the average procedure again last night, with new names. Something must have slipped."
Wren opens it. "No error message. It runs every time."
"So it is a logic error," Comet says. "The worst kind to find."
Nova projects an empty table with three columns: reading, total and count. "Would you like a hint?" she asks. "Trace it one pass at a time."
Wren hands you a pencil.
You will hand trace Beacon's average procedure, find the line with the bug, fix it, and test the fix.
PROCEDURE average(readings)
{
total ← 0
count ← 0
FOR EACH reading IN readings
{
total ← reading
count ← count + 1
}
RETURN(total / count)
} | Moment | reading | total | count |
|---|---|---|---|
| Before the loop | none yet | 0 | 0 |
| After pass 1 | 30 | 30 | 1 |
| After pass 2 | 60 | ? | ? |
| After pass 3 | 90 | ? | ? |
Now run the test set on both versions. Some tests pass even with the bug. That is why one test is never enough.
| Test readings | Expected | Buggy version | Fixed version |
|---|---|---|---|
| 30, 60, 90 | 60 | 30 | 60 |
| 0, 0, 0 (minimum) | 0 | 0 | 0 |
| 100, 100, 100 (maximum) | 100 | about 33 | 100 |
| 50 (one reading) | 50 | 50 | 50 |
| What the lab shows | True or false? |
|---|---|
| The test with one reading, 50, would have caught the bug. | ? |
| The test at the maximum, 100, 100, 100, catches the bug. | ? |
| After the fix, DISPLAY(total) inside the loop would show 30, 90, 180. | ? |
| A test that passes proves the procedure has no bugs. | ? |
Excellent debugging. Tomorrow you will write it all down so others can fix bugs too.