Skip to content

Lesson 3: 単純なバグのデバッグ

クラス: 初級
所要時間: 約40分
前提知識: 初級 Lesson 1〜2 完了済み


1. 解説

バグの種類と Claude Code の使い分け

バグの種類特徴Claude Code の活用法
構文エラー実行前にわかるエラーメッセージをそのまま貼る
実行時エラー実行中に発生スタックトレース + コードを渡す
論理エラー実行はされるが結果が違う「期待値 vs 実際値」を伝える
パフォーマンス遅い・メモリを食うプロファイル結果を見せる

効果的なバグ報告テンプレート

## バグ報告テンプレート

**ファイル**: src/utils.js

**再現手順**:
1. node -e "const u = require('./src/utils'); u.calculate([1,2,3])"
2. エラーが発生

**エラーメッセージ**:
TypeError: Cannot read properties of undefined (reading 'reduce')
    at calculate (src/utils.js:15:24)

**期待する動作**: [1,2,3] の合計 6 が返る
**実際の動作**: TypeError でクラッシュ

**追加情報**: Node.js v20、空配列を渡した場合は正常

デバッグの思考プロセス

1. エラーの種類を特定(構文/実行時/論理)
2. エラーの発生箇所を特定(スタックトレース)
3. 原因の仮説を立てる
4. 仮説を検証する(実行・ログ出力)
5. 修正して再検証

2. 実践

Step 1: バグだらけのコードを用意

bash
mkdir -p ~/claude-practice/elementary/lesson3
cd ~/claude-practice/elementary/lesson3

cat > buggy_app.js << 'EOF'
// ショッピングカートの計算ロジック
const TAX_RATE = 0.1;

function calcSubtotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.quatity, 0);  // スペルミス
}

function calcTax(subtotal) {
  return subtotal * TAX_RATE;
}

function calcTotal(items) {
  const subtotal = calcSubtotal(items);
  const tax = calcTax(subtotal);
  return subtotal + tax;  // 問題なさそうに見えるが...
}

function applyDiscount(total, discountCode) {
  const discounts = {
    'SAVE10': 0.1,
    'SAVE20': 0.2,
    'HALFOFF': 0.5
  };
  const rate = discounts[discountCode];
  return total - (total * rate);  // rate が undefined のときクラッシュ
}

function formatPrice(price) {
  return '$' + price.toFixed(2);
}

// テストデータ
const cartItems = [
  { name: 'Apple', price: 100, quantity: 2 },
  { name: 'Banana', price: 50, quantity: 3 },
  { name: 'Cherry', price: 200, quantity: 1 },
];

console.log('Subtotal:', formatPrice(calcSubtotal(cartItems)));
console.log('Total:', formatPrice(calcTotal(cartItems)));
console.log('With discount:', formatPrice(applyDiscount(calcTotal(cartItems), 'INVALID_CODE')));
EOF

Step 2: 実行してエラーを確認

bash
node buggy_app.js

エラーメッセージを確認してから Claude Code へ:

bash
claude
buggy_app.js を実行すると以下のエラーが出ます。
すべてのバグを見つけて修正してください。

[エラーメッセージを貼り付け]

修正前に:
1. 何個のバグが見つかったか
2. 各バグの種類と原因
を説明してください。

Step 3: 論理エラーを自分で発見させる

bash
node -e "
const app = require('./buggy_app');
// calcSubtotal のテスト(修正後)
"

修正後に期待値と比較:

修正後の calcSubtotal([{price:100, quantity:2}]) の結果が 200 になっていますか?
実際の計算を確認して、論理エラーが残っていないか検証してください。

Step 4: デバッグ用ログを追加させる

buggy_app.js の各関数の入口と出口にデバッグ用の console.log を追加してください。
デバッグが終わったら削除できるよう、// DEBUG: というプレフィックスを付けてください。

3. 確認課題(Assignment)

課題 3-1: 複数バグの一括修正

bash
cat > ~/claude-practice/elementary/lesson3/multi_bug.js << 'EOF'
function fibonacci(n) {
  if (n = 0) return 0;      // バグ1: = は代入
  if (n == 1) return 1;
  return fibonacci(n-1) + fibonacci(n-2);
}

function isPrime(n) {
  if (n < 2) return false;
  for (let i = 2; i < n; i++) {   // バグ2: i*i <= n が正しい(パフォーマンスバグ)
    if (n % i === 0) return false;
  }
  return true;
}

function reverseString(str) {
  return str.split('').reverse().join('');  // これは正しい
}

function countOccurrences(arr, target) {
  return arr.filter(x => x = target).length;  // バグ3: = は代入
}

console.log(fibonacci(10));
console.log(isPrime(17));
console.log(reverseString('hello'));
console.log(countOccurrences([1,2,3,2,1], 2));
EOF
multi_bug.js にあるすべてのバグを特定して修正してください。
バグの種類(構文エラー / 実行時エラー / 論理エラー / パフォーマンス)も分類してください。

達成条件: 3つのバグがすべて修正され、各関数が正しい結果を返すこと

課題 3-2: スタックトレースの読み解き

bash
cat > ~/claude-practice/elementary/lesson3/deep_error.js << 'EOF'
function processOrder(order) {
  const total = calculateTotal(order.items);
  return { orderId: order.id, total, tax: applyTax(total) };
}

function calculateTotal(items) {
  return items.map(item => getItemPrice(item)).reduce((a, b) => a + b);
}

function getItemPrice(item) {
  return item.product.price * item.quantity;
}

function applyTax(amount) {
  return amount * 0.1;
}

processOrder({
  id: 'ORD-001',
  items: [
    { product: { name: 'A', price: 100 }, quantity: 2 },
    { quantity: 3 },  // product が undefined
  ]
});
EOF
node ~/claude-practice/elementary/lesson3/deep_error.js

エラーとスタックトレースを Claude Code に渡して修正させせよ。

達成条件: 修正後に processOrderproduct が undefined のアイテムを適切に処理すること

課題 3-3: テストで検出されないバグ

bash
cat > ~/claude-practice/elementary/lesson3/silent_bug.js << 'EOF'
function getUniqueUsers(transactions) {
  const seen = {};
  return transactions.filter(t => {
    if (seen[t.userId]) return false;
    seen[t.userId] = true;
    return true;
  });
}

// テスト(パスするが実はバグがある)
const txs = [
  { userId: 1, amount: 100 },
  { userId: 2, amount: 200 },
  { userId: 1, amount: 300 },
];
console.assert(getUniqueUsers(txs).length === 2, 'should be 2 unique users');
console.log('Test passed!');
EOF
node ~/claude-practice/elementary/lesson3/silent_bug.js
silent_bug.js を読んでください。
テストはパスしていますが、特定のケースで正しく動作しない潜在的なバグがあります。
どんな入力値でバグが発生するか特定して修正してください。

ヒント: userId0false の場合を考えてみせよ。

達成条件: 潜在的なバグが発見・修正され、edge case でも正しく動作すること


自己チェックリスト


次の型

Lesson 4: Git 連携の基本 →

Claude Code Dojo