Debugging as a discipline
Hypothesis, bisection, and observability — replacing panic with method.
- Treat a bug as a falsifiable hypothesis to test
- Use bisection to localise a problem quickly
- Build observability so systems explain themselves
Debugging is not random poking until something works — it's a method, and a surprisingly scientific one. The beginner lesson taught you to read an error; this one teaches you to hunt a bug whose cause isn't obvious. The shift is from "try things" to "test hypotheses," and it makes you dramatically faster.
A bug is a falsifiable hypothesis
The scientific method, applied to code:
- Observe the failure precisely — what happens, with what input?
- Hypothesise a cause — "the list is empty when we reach this line."
- Predict something you'd see if you're right — "then this value should be null here."
- Test the prediction — add a check, inspect the value, run it.
- Confirm or reject, and repeat.
The discipline is forming a specific, testable guess instead of changing things at random. Random changes might hide the symptom while leaving the cause — and they teach you nothing.
Bisection: binary-search the problem
When you don't know where the bug is, don't read everything — bisect. Cut the problem in half and test which half contains it:
- In code: does the value look right halfway through the flow? That tells you which half to dig into. Repeat, halving each time.
- In history: if it worked last week, use version control to binary-search
the commits between then and now (
git bisectautomates this) to find the exact change that introduced it.
Bisection turns a search through a thousand lines (or commits) into about ten checks. It's the highest-leverage debugging move there is.
Observability: make systems explain themselves
You can only debug what you can see. Observability is building in the means to see:
- Logging — recording what happened and when.
- Tracing — following a single request through the whole system.
- Metrics — numbers over time that reveal trends and spikes.
Invest in this before the 2am incident, not during it. A system that explains itself is one you can debug calmly; a silent one leaves you guessing.
Fix the cause, not the symptom
The mark of discipline: once you find why, fix that. Patching the symptom — swallowing the error, special-casing the one input — leaves the real fault to resurface elsewhere. Confirm you understand the root cause before you call it fixed.
Reproduce, hypothesise, bisect, fix the cause, then add a test so the bug can never return silently. That last step turns a painful debug into permanent protection.
Where to go next
One last systems concern: when (and when not) to make things faster. Performance and tradeoffs closes out the track.