TTechSpecs

Systematic Debugging Skill

Systematic Debugging 是 Superpowers 中最重要的除錯型 skills 之一,專注於系統化地診斷和解決程式錯誤、bug 和異常行為。

何時使用

在以下情況中使用 Systematic Debugging skill:

必須使用的情境

  • 程式出現預期外的行為
  • 測試失敗且原因不明
  • 功能無法正常運作
  • 效能問題需要診斷
  • 收到使用者的 bug 回報

不適合的情境

  • 需要先明確問題(應先用 brainstorming)
  • 需要先驗證問題存在(應先用 verification)
  • 簡單的語法錯誤(直接修正即可)

系統化除錯流程

第 1 步:定義問題

清楚定義遇到的問題:

問題描述:
- 期望行為:點擊「刪除」按鈕後,項目從列表消失
- 實際行為:點擊後項目仍在列表中
- 重現步驟:1. 新增項目 → 2. 點擊刪除 → 3. 項目仍存在
- 錯誤訊息:無

第 2 步:收集資訊

系統化地收集相關資訊:

收集的資訊:
✓ 瀏覽器 console 訊息
✓ 網路請求狀態
✓ 應用程式 log
✓ 資料庫狀態
✓ 重現的步驟
✓ 問題發生的頻率

第 3 步:形成假設

基於收集的資訊形成假設:

假設 1:刪除按鈕的 onClick 事件沒正確綁定
假設 2:刪除 API 呼叫失敗但沒有錯誤處理
假設 3:前端狀態更新邏輯有誤
假設 4:刪除後重新抓取資料失敗

第 4 步:驗證假設

系統化地驗證每個假設:

驗證假設 1:
- 檢查按鈕的 onClick 屬性 ✓ 正確綁定
- 在 onClick 中加入 console.log ✓ 有被呼叫
→ 假設 1 不成立

驗證假設 2:
- 檢查網路請求 ✓ API 成功回應 200
- 檢查回應內容 ✓ 回應正確
→ 假設 2 不成立

驗證假設 3:
- 檢查狀態更新邏輯 ✓ 發現問題:setState 沒正確處理
→ 假設 3 成立!

第 5 步:實作修正

根據驗證結果實作修正:

// 問題程式碼
const handleDelete = (id: number) => {
  deleteTodo(id);
  setTodos(todos.filter(todo => todo.id !== id)); // ❌ todos 是舊值
};

// 修正後程式碼
const handleDelete = (id: number) => {
  deleteTodo(id);
  setTodos(prevTodos => prevTodos.filter(todo => todo.id !== id)); // ✅ 使用函式形式
};

第 6 步:驗證修正

確認修正有效:

驗證步驟:
✓ 點擊刪除按鈕
✓ 項目立即從列表消失
✓ 頁面刷新後項目仍消失(持久化正確)
✓ 多個項目刪除都正常
→ 修正成功!

如何使用

觸發詞

「使用 systematic-debugging skill 診斷刪除功能的問題」

實際範例

範例 1:診斷 API 錯誤

使用者輸入

使用 systematic-debugging skill 診斷使用者登入功能的問題

AI 回應

## 開始系統化除錯

### 第 1 步:定義問題

問題描述:
- 期望行為:輸入正確帳密後登入成功
- 實際行為:顯示「登入失敗」錯誤
- 重現步驟:1. 輸入正確 email 和密碼 → 2. 點擊登入 → 3. 顯示錯誤
- 錯誤訊息:「Invalid credentials」

### 第 2 步:收集資訊

檢查網路請求:
```http
POST /api/auth/login
Request: {
  "email": "user@example.com",
  "password": "password123"
}
Response: 401 Unauthorized
{
  "error": "Invalid credentials"
}

檢查後端 Log:

[INFO] Login attempt for: user@example.com
[ERROR] Password mismatch

第 3 步:形成假設

假設 1:前端密碼欄位名稱錯誤 假設 2:後端密碼驗證邏輯有誤 假設 3:資料庫中的密碼雜湊有問題

第 4 步:驗證假設

驗證假設 1:

  • 檢查前端表單 ✓ password 欄位正確
  • 檢查 API 呼叫 ✓ 傳送正確的 password → 假設 1 不成立

驗證假設 2:

  • 檢查後端驗證邏輯
// 發現問題
if (user.password_hash === password) { // ❌ 直接比較雜湊值和明文
  return true;
}

→ 假設 2 成立!

第 5 步:實作修正

// 修正後
import bcrypt from 'bcrypt';

if (await bcrypt.compare(password, user.password_hash)) { // ✅ 使用 bcrypt.compare
  return true;
}

第 6 步:驗證修正

測試登入: ✓ 正確密碼登入成功 ✓ 錯誤密碼顯示錯誤 ✓ 帳號不存在顯示錯誤

→ 問題解決!


### 範例 2:診斷效能問題

**使用者輸入**:

使用 systematic-debugging skill 診斷頁面載入緩慢的問題


**AI 回應**:

開始診斷效能問題

第 1 步:定義問題

問題描述:

  • 期望行為:頁面在 2 秒內載入完成
  • 實際行為:首屏載入需要 8 秒
  • 影響範圍:所有使用者都遇到
  • 開始時間:最近一週開始出現

第 2 步:收集資訊

使用 Chrome DevTools 分析:

Performance 分析:
- JavaScript 執行:5.2 秒
- 渲染:1.8 秒
- 網路請求:1 秒

主要耗時項:
- Data fetching: 4 秒
- Component rendering: 1.2 秒

Network 分析:

緩慢的 API:
- GET /api/items: 3.8 秒
- GET /api/categories: 0.2 秒

第 3 步:形成假設

假設 1:API 查詢效率低(缺少索引) 假設 2:API 回傳過多資料 假設 3:前端資料處理邏輯低效 假設 4:Component 重複渲染

第 4 步:驗證假設

驗證假設 1:

  • 檢查資料庫查詢
SELECT * FROM items;  -- 全表掃描,無索引

→ 問題確認!

驗證假設 2:

  • 檢查 API 回應大小:2.5 MB
  • 檢查欄位:包含不必要的大文字欄位 → 也是問題!

第 5 步:實作修正

-- 修正 1:加上索引
CREATE INDEX idx_items_category ON items(category);

-- 修正 2:優化查詢
SELECT id, name, price FROM items
WHERE category = ?
LIMIT 50;
// 修正 3:前端只抓取必要資料
const { data } = await useFetch('/api/items?fields=id,name,price&limit=50');

第 6 步:驗證修正

效能測試:

  • API 回應時間:3.8 秒 → 0.3 秒
  • 頁面載入時間:8 秒 → 1.8 秒 → 效能大幅改善!

## 除錯技巧

### 1. 二分法

使用二分法快速定位問題:

將程式分為前後兩段:

  • 前半段正常 → 問題在後半段
  • 後半段正常 → 問題在前半段

持續二分直到定位到問題


### 2. 最小化重現

建立最小化的重現案例:

```typescript
// 複雜的問題情境
// → 簡化為最小程式碼

function reproduceBug() {
  const result = processItem({ id: 1, name: 'Test' });
  console.log(result);  // 預期 X,實際 Y
}

3. 日誌追蹤

使用日誌系統化追蹤:

function handleDelete(id: number) {
  console.log('[DEBUG] handleDelete called with id:', id);
  const response = await deleteItem(id);
  console.log('[DEBUG] deleteItem response:', response);
  updateState();
  console.log('[DEBUG] state updated');
}

4. 漸進式隔離

逐步隔離問題範圍:

第 1 步:確定是前端還是後端問題
第 2 步:確定是哪個模組的問題
第 3 步:確定是哪個函式的問題
第 4 步:確定是哪行程式碼的問題

除錯工具

前端除錯工具

  • Browser DevTools:Console、Network、Performance
  • React DevTools:Component 樹、State、Props
  • Vue DevTools:組件樹、Vuex state

後端除錯工具

  • Logging: Winston、Pino、Bunyan
  • Debugger:Node.js Inspector、Chrome DevTools
  • APM:New Relic、Data Dog

資料庫除錯工具

  • Query Analyzer:EXPLAIN、Slow Query Log
  • Monitoring:Prometheus、Grafana

常見錯誤模式

1. 非同步錯誤

// ❌ 錯誤
const result = fetchData();
console.log(result);  // undefined

// ✅ 正確
const result = await fetchData();
console.log(result);  // 正確資料

2. 狀態錯誤

// ❌ 錯誤:使用舊狀態
setTodos([...todos, newTodo]);

// ✅ 正確:使用函式形式
setTodos(prevTodos => [...prevTodos, newTodo]);

3. 型別錯誤

// ❌ 錯誤:沒有型別檢查
function process(data: any) {
  return data.value;  // 可能是 undefined
}

// ✅ 正確:使用型別
function process(data: { value: string }) {
  return data.value;
}

與其他 Skills 組合

推薦組合

Verification + Systematic Debugging

verification-before-completion → systematic-debugging

先驗證問題存在,再系統化除錯

Systematic Debugging + Test-Driven Development

systematic-debugging → test-driven-development

除錯後加入測試防止回歸

最佳實踐

1. 保持冷靜

遇到 bug 時保持系統化思考:

  • 不要盲目嘗試
  • 系統化地收集資訊
  • 形成假設後再驗證

2. 記錄學習

將除錯過程記錄下來:

除錯筆記:
- 問題描述
- 解決過程
- 最終方案
- 預防措施

3. 建立測試

除錯後建立回歸測試:

test('should delete item correctly', () => {
  // 確保 bug 不會再出現
});

4. 根本原因分析

不只解決症狀,要找到根本原因:

症狀:頁面載入緩慢

直接原因:API 查詢慢

根本原因:缺少資料庫索引

解決方案:加上索引

Systematic Debugging 是解決程式問題的關鍵 skill,系統化的除錯方法能大幅提升解決效率!