Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Debugging compositions

โญโญ intermediateโณ 12 min read๐Ÿ“ Lesson 95 of 256

Isolate each helper against its contract; trace where the poison enters.

Debugging a composition means isolating the lying part. Strategy: test each helper against the contract in isolation, because a wrong helper poisons everything downstream.

// CONTRACT: number of words strictly longer than average length
public static int longWords(String[] words) {
    int sum = 0;
    for (String w : words) { sum += w.length(); }
    double avg = (double) sum / words.length;
    int count = 0;
    for (String w : words) {
        if (w.length() > avg) { count++; }
    }
    return count;
}

Trace {""ab"", ""cd"", ""abcde""}: sum = 2 + 2 + 5 = 9, avg = 3.0. Words longer than 3.0: just ""abcde"" โ†’ 1. Both halves look right โ€” the bug (when present) is usually one of: integer division in avg (missing the (double) cast โ†’ truncates to 3, same answer here but wrong for sum=8), division by zero for an empty array (precondition violation โ€” the spec would promise non-empty), or the wrong comparison at the end.

The isolation habit: to test the average alone, return avg instead of count once, run the case, restore. On the exam (no compiler), the equivalent is tracing each helper once with a hand case where the correct value is known โ€” a 3-element trace exposes most compositional bugs in under a minute.