# Systematic Debugging — From Symptom to Root Cause

<!-- hint:slides topic="Systematic debugging: observe-hypothesize-test loop, binary search, reading stack traces, and cause vs symptom" slides="5" -->

## The Scientific Method Applied

Debugging is hypothesis-driven. You observe, hypothesize, test, and conclude — then repeat until you find the root cause.

```
Observe → Hypothesize → Test → Conclude → (repeat if needed)
```

```mermaid
flowchart LR
    A[Observe] --> B[Hypothesize]
    B --> C[Predict]
    C --> D[Test]
    D --> E[Analyze]
    E --> F{Found?}
    F -->|No| B
    F -->|Yes| G[Fix]
```

## Reproduce First

Before changing anything, **reproduce the bug consistently**. If you can't reproduce it, you can't verify your fix.

- Note exact steps, inputs, and environment
- Check timing (does it only happen under load?)
- Capture logs, screenshots, or error messages

## Binary Search for the Cause

Narrow the problem space efficiently:

1. **Halve the input** — Does it fail with half the data? Which half?
2. **Disable features** — Does it fail with feature X off?
3. **Bisect history** — Which commit introduced it? (`git bisect`)

```javascript
// Instead of reading 1000 lines, binary search:
// 1. Comment out half the code — still fails?
// 2. Narrow to the half that matters
// 3. Repeat until you isolate the culprit
```

## Rubber Duck Debugging

Explain the problem out loud (or to a rubber duck, colleague, or AI). Often the act of explaining reveals the bug before you finish.

"Why would this fail when… oh. I see. The loop starts at 1 but the array is 0-indexed."

## Reading Stack Traces

Stack traces show the **call path** when the error occurred:

```
Error: Cannot read property 'id' of undefined
    at UserCard (./src/UserCard.jsx:15:22)
    at UserList (./src/UserList.jsx:8:14)
    at App (./src/App.jsx:12:10)
```

Read **bottom to top**: `App` rendered `UserList`, which rendered `UserCard`, where line 15 accessed `.id` on `undefined`. The bug is likely in `UserCard` (wrong prop) or `UserList` (passing undefined).

## Debugger Tools

### Breakpoints
Pause execution at a line. Inspect variables, step through.

```javascript
function calculateTotal(items) {
  let total = 0;
  for (const item of items) {
    total += item.price * item.quantity;  // Breakpoint here
  }
  return total;
}
```

### Watches
Monitor expressions (e.g., `item.price`, `total`) as you step.

### Call Stack
See how you got here. Click frames to jump to caller context.

### Conditional Breakpoints
Break only when a condition holds (e.g., `item.id === 42`).

## Logging Strategies

| Strategy | Use When |
|----------|----------|
| `console.log` | Quick inspection; remove after |
| Structured logging | Production; levels (debug, info, warn, error) |
| Correlation IDs | Tracing a request across services |
| Minimal repro | Log only inputs and outputs around the fault |

```javascript
// Good: log enough to understand flow
console.log('calculateTotal input:', { items, count: items.length });
const total = calculateTotal(items);
console.log('calculateTotal output:', total);
```

## Common Pitfalls

| Pitfall | Problem |
|---------|---------|
| Fixing symptoms not causes | Patch hides the bug; it returns elsewhere |
| Assuming without testing | "It must be X" — verify |
| Changing multiple things | Can't tell what fixed it |
| Not reproducing first | "Fixed" but bug was intermittent |
| Giving up too soon | Systematic search almost always finds it |

## Debugging Process Flow

```mermaid
flowchart TD
    A[Observe: Symptom] --> B[Reproduce consistently]
    B --> C[Form hypothesis]
    C --> D[Design test]
    D --> E{Test confirms?}
    E -->|Yes| F[Identify root cause]
    E -->|No| C
    F --> G[Fix cause, not symptom]
    G --> H[Verify fix with repro steps]
```

---

## Key Takeaways

1. **Reproduce first** — no fix without a reliable repro
2. **Hypothesize and test** — don't guess randomly
3. **Binary search** — halve the problem space
4. **Use the debugger** — breakpoints, watches, call stack
5. **Fix the cause** — not the symptom
6. **Rubber duck** — explaining often reveals the answer
