Systematic Debugging
Core Principle
Don't guess. Investigate systematically.
After 3 failed fix attempts, STOP and question the architecture.
Phase 1: Understand the Problem
Gather Information
- •What is the expected behavior?
- •What is the actual behavior?
- •When did it start failing?
- •What changed recently?
Reproduce Consistently
- •Create minimal reproduction case
- •Document exact steps to reproduce
- •Identify if it's deterministic or intermittent
Check the Obvious First
- •Is it plugged in? (Services running, dependencies installed)
- •Are you in the right environment?
- •Did you save the file?
- •Is the cache cleared?
Phase 2: Root Cause Tracing
Backward Tracing Technique
- •Where does the bad value appear?
- •What called this with the bad value?
- •Keep tracing up until you find the source
- •Fix at source, not at symptom
Find Working Examples
- •Locate similar working code in same codebase
- •What works that's similar to what's broken?
- •Compare against references
Identify Differences
- •What's different between working and broken?
- •List every difference, however small
- •Don't assume "that can't matter"
Phase 3: Form Hypothesis
Scientific Method
- •Form a SINGLE hypothesis
- •Predict what you'd see if hypothesis is true
- •Design a test to verify
- •Run the test
- •If wrong, form new hypothesis based on new data
Don't Multi-Hypothesis
- •One hypothesis at a time
- •Test it completely before moving on
- •Don't mix debugging approaches
Phase 4: Implement Fix
Write Failing Test First
- •Test that reproduces the bug
- •Test should fail before fix
- •Test should pass after fix
Single Fix at a Time
- •ONE change only
- •No "while I'm here" improvements
- •No bundled refactoring
Verify Completely
- •Original test passes
- •No other tests broken
- •Issue actually resolved
- •Edge cases covered
Phase 5: If Fix Doesn't Work
After Each Failed Attempt
- •STOP
- •Count: How many fixes have you tried?
- •If < 3: Return to Phase 1, re-analyze with new information
- •If ≥ 3: STOP and question the architecture
After 3+ Failed Fixes
Pattern indicating architectural problem:
- •Each fix reveals new problems elsewhere
- •Fixes require "massive refactoring"
- •Each fix creates new symptoms
STOP and ask:
- •Is this pattern fundamentally sound?
- •Is this the right abstraction?
- •Should this be redesigned?
Debugging Tools
Logging Strategy
code
// Add context to logs
console.log('[ComponentName] methodName:', {
input,
state: relevantState,
timestamp: Date.now()
});
Binary Search Debugging
- •Add log at midpoint of suspect code
- •Determine if bug is before or after
- •Repeat until isolated
Rubber Duck Debugging
Explain the problem out loud:
- •What should happen?
- •What actually happens?
- •What did I try?
- •What assumptions am I making?
Common Pitfalls
Avoid These Mistakes
- •Changing multiple things at once
- •Assuming you know the cause
- •Fixing symptoms instead of root cause
- •Not verifying the fix actually works
- •Not adding regression tests
Red Flags
- •"It works on my machine"
- •"It was working yesterday"
- •"I didn't change anything"
- •"That can't be the problem"