Skill 寫法圖鑑

debugging-strategies

wshobson | 除錯與調查 | 原文 | MIT

系統化除錯方法:重現、收集資訊、提假設、驗證,加上各類 bug 的對策

中文翻譯

---
name: debugging-strategies
description: 精通系統化除錯技巧、profiling 工具與根因分析,能在任何 codebase 或技術棧中有效率地追出 bug。適用於調查 bug、效能問題或非預期行為的時候。
---

# 除錯策略

用經過驗證的策略、強大的工具和有條理的方法,把除錯從令人沮喪的亂猜,變成系統化的問題解決。

## 什麼時候用這個 Skill

- 追查難抓的 bug
- 調查效能問題
- 理解不熟悉的 codebase
- 除錯 production 問題
- 分析 crash dump 與 stack trace
- Profiling 應用程式效能
- 調查記憶體洩漏
- 除錯分散式系統

## 核心原則

### 1. 科學方法

**1. 觀察**:實際的行為是什麼?
**2. 提出假設**:可能是什麼造成的?
**3. 實驗**:測試你的假設
**4. 分析**:結果證實還是推翻了你的理論?
**5. 重複**:一直做到找出根因為止

### 2. 除錯心態

**不要預設:**

- 「不可能是 X」:不,就是有可能
- 「我沒動過 Y」:還是要檢查
- 「在我的機器上是好的」:去查為什麼

**要做:**

- 穩定地重現問題
- 隔離問題
- 做詳細的筆記
- 質疑每一件事
- 卡住的時候休息一下

### 3. 橡皮鴨除錯法

把你的程式碼和問題大聲講出來(對橡皮鴨、同事,或自己都行),常常就會發現問題在哪。

## 系統化除錯流程

### 階段 1:重現

```markdown
## 重現檢查表

1. **你能重現嗎?**
   - 每次都會?有時候?隨機發生?
   - 需要特定條件嗎?
   - 別人也能重現嗎?

2. **建立最小重現案例**
   - 簡化到最小的範例
   - 移除不相關的程式碼
   - 隔離問題

3. **記錄步驟**
   - 寫下確切的步驟
   - 記下環境細節
   - 擷取錯誤訊息
```

### 階段 2:收集資訊

```markdown
## 資訊收集

1. **錯誤訊息**
   - 完整的 stack trace
   - 錯誤碼
   - Console/log 輸出

2. **環境**
   - 作業系統版本
   - 語言/runtime 版本
   - 相依套件的版本
   - 環境變數

3. **最近的變更**
   - Git 歷史
   - Deploy 時間線
   - 設定變更

4. **範圍**
   - 影響所有使用者還是特定使用者?
   - 所有瀏覽器還是特定瀏覽器?
   - 只有 production 還是 dev 也會?
```

### 階段 3:形成假設

```markdown
## 形成假設

根據收集到的資訊,問自己:

1. **什麼改變了?**
   - 最近的程式碼變更
   - 相依套件更新
   - 基礎設施變更

2. **有什麼不一樣?**
   - 正常 vs 異常的環境
   - 正常 vs 異常的使用者
   - 之前 vs 之後

3. **可能在哪裡出問題?**
   - 輸入驗證
   - 商業邏輯
   - 資料層
   - 外部服務
```

### 階段 4:測試與驗證

```markdown
## 測試策略

1. **二分搜尋**
   - 把一半的程式碼註解掉
   - 縮小問題區段的範圍
   - 重複直到找到

2. **加 log**
   - 在關鍵位置放 console.log/print
   - 追蹤變數的值
   - 追蹤執行流程

3. **隔離元件**
   - 個別測試每個部分
   - Mock 相依項目
   - 移除複雜度

4. **比較正常與異常**
   - Diff 設定
   - Diff 環境
   - Diff 資料
```

在挑選除錯工具,或進行 bisect、differential、trace、記憶體分析之前,先讀 `references/tools-and-techniques.md`。

## 依問題類型的除錯模式

### 模式 1:間歇性 bug

```markdown
## 不穩定 bug 的對策

1. **加上大量 log**
   - 記錄時間資訊
   - 記錄所有狀態轉換
   - 記錄外部互動

2. **找 race condition**
   - 對共享狀態的並行存取
   - 非同步操作以錯誤的順序完成
   - 缺少同步機制

3. **檢查時間相依性**
   - setTimeout/setInterval
   - Promise 的 resolve 順序
   - Animation frame 的時機

4. **壓力測試**
   - 跑很多次
   - 改變時間
   - 模擬負載
```

### 模式 2:效能問題

```markdown
## 效能除錯

1. **先 profile**
   - 不要盲目最佳化
   - 前後都要量測
   - 找出瓶頸

2. **常見元凶**
   - N+1 query
   - 不必要的 re-render
   - 大量資料處理
   - 同步 I/O

3. **工具**
   - 瀏覽器 DevTools 的 Performance 分頁
   - Lighthouse
   - Python:cProfile、line_profiler
   - Node:clinic.js、0x
```

### 模式 3:Production bug

```markdown
## Production 除錯

1. **蒐集證據**
   - 錯誤追蹤(Sentry、Bugsnag)
   - 應用程式 log
   - 使用者回報
   - 指標/監控

2. **在本機重現**
   - 使用 production 資料(匿名化後)
   - 對齊環境
   - 照著確切的步驟做

3. **安全地調查**
   - 不要動 production
   - 使用 feature flag
   - 加上監控/log
   - 在 staging 測試修正
```

## 最佳實務

1. **先重現**:重現不了就修不了
2. **隔離問題**:一直拿掉複雜度,直到剩下最小案例
3. **讀錯誤訊息**:它們通常很有用
4. **檢查最近的變更**:大部分 bug 都是最近才出現的
5. **用版本控制**:Git bisect、blame、history
6. **休息一下**:換個腦袋更容易看出問題
7. **記錄發現**:幫未來的自己一個忙
8. **修根因**:不要只修症狀

## 常見的除錯錯誤

- **一次改很多東西**:一次只改一件事
- **不讀錯誤訊息**:要讀完整的 stack trace
- **以為問題很複雜**:通常很簡單
- **在 prod 留著 debug log**:出貨前要移除
- **不用 debugger**:console.log 不一定是最好的
- **太早放棄**:堅持會有回報
- **沒測試修正**:要驗證它真的有效

## 快速除錯檢查表

```markdown
## 卡住的時候,檢查:

- [ ] 拼字錯誤(變數名稱打錯)
- [ ] 大小寫(fileName vs filename)
- [ ] Null/undefined 值
- [ ] 陣列索引差一
- [ ] 非同步時機(race condition)
- [ ] Scope 問題(closure、hoisting)
- [ ] 型別不符
- [ ] 缺少相依套件
- [ ] 環境變數
- [ ] 檔案路徑(絕對 vs 相對)
- [ ] 快取問題(清除快取)
- [ ] 過期資料(重新整理資料庫)
```

英文原文

---
name: debugging-strategies
description: Master systematic debugging techniques, profiling tools, and root cause analysis to efficiently track down bugs across any codebase or technology stack. Use when investigating bugs, performance issues, or unexpected behavior.
---

# Debugging Strategies

Transform debugging from frustrating guesswork into systematic problem-solving with proven strategies, powerful tools, and methodical approaches.

## When to Use This Skill

- Tracking down elusive bugs
- Investigating performance issues
- Understanding unfamiliar codebases
- Debugging production issues
- Analyzing crash dumps and stack traces
- Profiling application performance
- Investigating memory leaks
- Debugging distributed systems

## Core Principles

### 1. The Scientific Method

**1. Observe**: What's the actual behavior?
**2. Hypothesize**: What could be causing it?
**3. Experiment**: Test your hypothesis
**4. Analyze**: Did it prove/disprove your theory?
**5. Repeat**: Until you find the root cause

### 2. Debugging Mindset

**Don't Assume:**

- "It can't be X" - Yes it can
- "I didn't change Y" - Check anyway
- "It works on my machine" - Find out why

**Do:**

- Reproduce consistently
- Isolate the problem
- Keep detailed notes
- Question everything
- Take breaks when stuck

### 3. Rubber Duck Debugging

Explain your code and problem out loud (to a rubber duck, colleague, or yourself). Often reveals the issue.

## Systematic Debugging Process

### Phase 1: Reproduce

```markdown
## Reproduction Checklist

1. **Can you reproduce it?**
   - Always? Sometimes? Randomly?
   - Specific conditions needed?
   - Can others reproduce it?

2. **Create minimal reproduction**
   - Simplify to smallest example
   - Remove unrelated code
   - Isolate the problem

3. **Document steps**
   - Write down exact steps
   - Note environment details
   - Capture error messages
```

### Phase 2: Gather Information

```markdown
## Information Collection

1. **Error Messages**
   - Full stack trace
   - Error codes
   - Console/log output

2. **Environment**
   - OS version
   - Language/runtime version
   - Dependencies versions
   - Environment variables

3. **Recent Changes**
   - Git history
   - Deployment timeline
   - Configuration changes

4. **Scope**
   - Affects all users or specific ones?
   - All browsers or specific ones?
   - Production only or also dev?
```

### Phase 3: Form Hypothesis

```markdown
## Hypothesis Formation

Based on gathered info, ask:

1. **What changed?**
   - Recent code changes
   - Dependency updates
   - Infrastructure changes

2. **What's different?**
   - Working vs broken environment
   - Working vs broken user
   - Before vs after

3. **Where could this fail?**
   - Input validation
   - Business logic
   - Data layer
   - External services
```

### Phase 4: Test & Verify

```markdown
## Testing Strategies

1. **Binary Search**
   - Comment out half the code
   - Narrow down problematic section
   - Repeat until found

2. **Add Logging**
   - Strategic console.log/print
   - Track variable values
   - Trace execution flow

3. **Isolate Components**
   - Test each piece separately
   - Mock dependencies
   - Remove complexity

4. **Compare Working vs Broken**
   - Diff configurations
   - Diff environments
   - Diff data
```

Before selecting debugging tools or performing bisect, differential, trace, or memory analysis, read `references/tools-and-techniques.md`.

## Debugging Patterns by Issue Type

### Pattern 1: Intermittent Bugs

```markdown
## Strategies for Flaky Bugs

1. **Add extensive logging**
   - Log timing information
   - Log all state transitions
   - Log external interactions

2. **Look for race conditions**
   - Concurrent access to shared state
   - Async operations completing out of order
   - Missing synchronization

3. **Check timing dependencies**
   - setTimeout/setInterval
   - Promise resolution order
   - Animation frame timing

4. **Stress test**
   - Run many times
   - Vary timing
   - Simulate load
```

### Pattern 2: Performance Issues

```markdown
## Performance Debugging

1. **Profile first**
   - Don't optimize blindly
   - Measure before and after
   - Find bottlenecks

2. **Common culprits**
   - N+1 queries
   - Unnecessary re-renders
   - Large data processing
   - Synchronous I/O

3. **Tools**
   - Browser DevTools Performance tab
   - Lighthouse
   - Python: cProfile, line_profiler
   - Node: clinic.js, 0x
```

### Pattern 3: Production Bugs

```markdown
## Production Debugging

1. **Gather evidence**
   - Error tracking (Sentry, Bugsnag)
   - Application logs
   - User reports
   - Metrics/monitoring

2. **Reproduce locally**
   - Use production data (anonymized)
   - Match environment
   - Follow exact steps

3. **Safe investigation**
   - Don't change production
   - Use feature flags
   - Add monitoring/logging
   - Test fixes in staging
```

## Best Practices

1. **Reproduce First**: Can't fix what you can't reproduce
2. **Isolate the Problem**: Remove complexity until minimal case
3. **Read Error Messages**: They're usually helpful
4. **Check Recent Changes**: Most bugs are recent
5. **Use Version Control**: Git bisect, blame, history
6. **Take Breaks**: Fresh eyes see better
7. **Document Findings**: Help future you
8. **Fix Root Cause**: Not just symptoms

## Common Debugging Mistakes

- **Making Multiple Changes**: Change one thing at a time
- **Not Reading Error Messages**: Read the full stack trace
- **Assuming It's Complex**: Often it's simple
- **Debug Logging in Prod**: Remove before shipping
- **Not Using Debugger**: console.log isn't always best
- **Giving Up Too Soon**: Persistence pays off
- **Not Testing the Fix**: Verify it actually works

## Quick Debugging Checklist

```markdown
## When Stuck, Check:

- [ ] Spelling errors (typos in variable names)
- [ ] Case sensitivity (fileName vs filename)
- [ ] Null/undefined values
- [ ] Array index off-by-one
- [ ] Async timing (race conditions)
- [ ] Scope issues (closure, hoisting)
- [ ] Type mismatches
- [ ] Missing dependencies
- [ ] Environment variables
- [ ] File paths (absolute vs relative)
- [ ] Cache issues (clear cache)
- [ ] Stale data (refresh database)
```