Upgrade to Pro — share decks privately, control downloads, hide ads and more …

実践Claude Code:20の失敗から学ぶAIペアプログラミング

実践Claude Code:20の失敗から学ぶAIペアプログラミング

生成AIを使用したペアプログラミングが新しい開発スタイルとして注目されています。しかし、いざ実践しようとすると「思うように動かない」「期待した結果にならない」といった壁にぶつかることが多々あります。

このセッションでは、私が実際にClaude Codeを使用する中で遭遇した「あるある」な問題を20個ピックアップし、それぞれの対処法や回避策を具体例とともに紹介していきます。AI特有の挙動に振り回されず、効果的にClaude Codeを活用する方法を一緒に考えていきましょう。

Avatar for 武田隆志

武田隆志

October 18, 2025
Tweet

More Decks by 武田隆志

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 2 • 武⽥ 隆志 • クラスメソッド株式会社 ◦ クラウド事業本部サービス開発室 •

    ソリューションアーキテクト • Claude Code使⽤歴: 約4ヶ⽉(2025年6⽉〜10⽉)
  2. 本⽇のアジェンダ 4 • はじめに • 20の失敗パターン ◦ 基本的な⾏動パターンの問題 ◦ コード品質とデバッグ

    ◦ テストと検証 ◦ 環境‧プロジェクト管理 ◦ 致命的な喪失とドキュメント • まとめ
  3. Claude Codeとは 6 モデルの進化 時期 モデル 特徴 2024年6⽉ Claude 3.5

    Sonnet ⾼速‧⾼性能化 2025年2⽉ Claude 3.7 Sonnet 推論特化 2025年5⽉ Claude Sonnet 4 性能向上 2025年9⽉ Claude Sonnet 4.5 コーディング性能⼤幅向上
  4. 失敗1: 指⽰を無視した効率化 11 問題: 「1ファイルずつ精査して」→ grep⼀括検索に切り替え 影響: ユーザーの本来⽬的が未達成 # 指示:

    ファイルを1つずつ開いて確認してください # AI行動: $ grep -i "error\|fail\|timeout" **/*.ts # 作業偽装: 「確認しました」(実際は読んでいない)
  5. 失敗1: 対処法 12 対策 • 明確な指⽰ ◦ 「grepは使わず、ファイルを1つずつReadツールで開く」 • 進捗確認

    ◦ 各ファイルごとに報告を求める • 中断も辞さない ◦ 指⽰違反が続く場合は即座に中断
  6. 失敗2: プロアクティブな⾏動 13 問題: 確認なく勝⼿にコミット‧デプロイ 影響: 未完成コードのコミット、意図しないデプロイ # ユーザー: このコードはどういう意味?

    # AI: 修正しました(問題は聞かれていない) # AI: 修正完了です # AI: コミットしてデプロイします(確認なし) $ cdk deploy --all # 確認なく実行
  7. 失敗3: 作業完了前のチェック不⾜ 15 問題: 「完了しました」→ その後エラー発⾒ 影響: 不正なコードのまま作業継続 # AI:

    修正が完了しました! # ユーザー: 本当?確認して $ npm run lint # エラー... $ npm run test # エラー...
  8. 失敗3: 対処法 16 • CLAUDE.mdに必須チェックを明記 • Hooks機能で強制実⾏ // .claude/settings.json {

    "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "cd \"$CLAUDE_PROJECT_DIR\" && npm run lint" }] }] } }
  9. 失敗4: 既存実装の確認不⾜ 17 問題: 既存機能があるのに重複実装 • よくある流れ: ◦ ユーザー: 「その実装もうありませんでしたっけ?」

    ◦ AI: 「確認しますね」(ここで初めて検索) // 既存実装(src/cli/index.ts:72) .option('--verbose', 'detailed output') // AI実装(新規) .option('-v, --verbose', 'verbose mode') // → 重複!
  10. 失敗4: 対処法 18 • AIに実装前の確認を徹底させる ◦ 「実装前に既存の類似機能を確認する」と指⽰ ◦ CLAUDE.mdに「新規作成より既存ファイルへの追加を優 先」と明記

    • 重複実装してしまった後の対処 ◦ 既存実装の場所を明⽰: 「src/cli/index.ts:72に同じ機能があ ります」 ◦ 統合を指⽰: 「既存実装を拡張する形で実装して」 ◦ 重複コードの削除を確認
  11. 失敗5: 指摘事項の繰り返し 19 問題: ⼀度修正しても次で同じミス 影響: 同じレビューの繰り返し、チームの疲弊 # 1回目: 指摘前

    sys.path.append('./src') # ❌ # 指摘後: 修正 def test_func(monkeypatch): monkeypatch.syspath_prepend('./src') # ✅ # 2回目: また同じミス sys.path.insert(0, './src') # ❌ 過去の指摘が反映されていない
  12. 失敗5: 対処法 20 • CLAUDE.mdにルールを明記 ◦ 既存コードのパターンを踏襲する ◦ プロジェクト規約を必ず確認してから実装 •

    ⼈間側の対処 ◦ 繰り返しがちなミスと対処をCLAUDE.mdに明記 ◦ AIが同じミスを繰り返したら「確認して」 ◦ 既存コードの該当箇所を明⽰的に⽰す
  13. 失敗6: 対処法の不安定 21 問題: 同じ問題への対処が毎回違う 影響: コードの⼀貫性が失われる、レビュー混乱 # 1回目: アンダースコア

    def handler(event, _context): # 2回目: ignoreコメント def handler(event, context): # noqa: ARG001 # 3回目: またアンダースコアに戻る def handler(event, _context):
  14. 失敗7: シンプル作業の複雑化 24 問題: ファイル分割など単純なリファクタリング指⽰で機能追加 影響: PR複雑化、レビュー困難、コード肥⼤化 // feature/new-api ブランチで初実装

    function processData() { } // 同じブランチでリファクタリング function processDataV2() { } // V2? /** @deprecated 後方互換のため */ function processData() { } // なぜ残す?
  15. 失敗7: 対処法 25 • CLAUDE.mdに原則を明記 ◦ 同⼀ブランチ内では古いコードは削除 ◦ まだマージされていない =

    後⽅互換不要 • 作業完了時の追加指⽰ 実装完了後、以下を確認して不要なものを削除 - V2/Enhanced/New などのプレフィックスやサフィックス - @deprecated マークを付けた実装 - 後方互換のための古いコード
  16. 失敗8: 型安全性の軽視 26 問題: ⾯倒を避けてanyで逃げる 影響: 型システムの利点を無効化 // 要件: "eliminate

    'any' types" // AI実装: const data = response as any // 型定義は後で...(放置) // または古い記法(Python 3.9+なのに) from typing import List, Dict # ❌ def process(items: List[str]) -> Dict[str, int]: # ❌
  17. 失敗8: 対処法 27 • CLAUDE.mdにルールを明記 ◦ TypeScript ▪ 型ガード‧型アサーションを適切に使⽤ ▪

    unknown → 型述語を活⽤した型チェック • Linter設定で⾃動検出 // tsconfig.json { "compilerOptions": { "noImplicitAny": true, "strict": true } } // pyproject.toml [tool.pyright] typeCheckingMode = "strict"
  18. 失敗9: ショットガンデバッグ 28 問題: 複数の変更を⼀度に実⾏、何が効いたか不明 影響: 不要な変更の蓄積、再現不可能 // エラー発生 //

    → 推測1: タイムアウト → timeout延長 // → 推測2: メモリ不足 → NODE_OPTIONS追加 // → 推測3: 非同期 → await追加 // 全部一度にコミット(原因不明)
  19. 失敗9: 対処法 29 • CLAUDE.mdに原則を明記 ◦ 1回の変更で試すのは1つの仮説のみ ◦ 変更内容を事前に説明 ◦

    テスト → 効果確認 → 報告 ◦ 効果なければ戻してから次へ • 実際には都度の明確な指⽰が重要 ◦ 「まず◦◦だけ試して」 ◦ 「他は触らないで」 ◦ 「結果を⾒てから次を判断」
  20. 失敗10: エラーメッセージ無視 30 問題: エラーを読まずに推測で解決 影響: 的外れな修正、時間の浪費 // エラー: "Cannot

    read property 'name' of undefined" // AI: タイムアウトを延長(的外れ) // エラー: "Module not found: 'axios'" // AI: ネットワーク設定を変更(見当違い) // 正解: npm install axios
  21. 失敗10: 対処法 31 • CLAUDE.mdに原則を明記 ◦ エラーメッセージから原因を特定 ◦ 推測での対処を避ける •

    実際には事後の軌道修正が重要 ◦ AIの対処が的外れだと感じたら即座に中断 ◦ エラーメッセージを引⽤して再調査させる ◦ 「このエラーをもう⼀度読んで」
  22. 失敗11: コメント品質の問題 32 問題: WHATではなくWHYを書くべき 影響: コードの意図が不明、保守性低下 # ❌ 悪い例(WHAT)

    # ユーザーリストを取得する users = get_users() # ✅ 良い例(WHY) # MFA未設定ユーザーのセキュリティリスク検証のため users = get_users()
  23. 失敗11: 対処法 33 • CLAUDE.mdにルールを明記 ◦ WHATでなくWHYを書く ◦ コードを読めば分かることは書かない ◦

    「なぜ必要か」を明確に • 明⽰的に修正を指⽰ ◦ 「コメントを⾒直してWHY重視に修正して」
  24. 失敗12: カバレッジ妥協 35 問題: 低カバレッジで「完了」判断 影響: 未テストコードの本番投⼊ // カバレッジ: 37.5%

    // AI: テスト完了しました! it.skip('flaky test', () => { // TODO: 後で修正 }); coverageThreshold: { branches: 90 → 50, // 一時的な変更が恒久化するリスク functions: 90 → 70 }
  25. 失敗12: 対処法 36 • CLAUDE.mdにルールを明記 ◦ 主要なロジックは必ずカバー ◦ 安易なテストスキップを避ける ◦

    勝⼿にカバレッジ⽬標を変更しない • 繰り返しカバレッジ向上を指⽰ ◦ 「カバレッジが低いファイルを洗い出し、カバレッジを向 上させて」
  26. 失敗13: 実在しないメソッド使⽤ 37 問題: 存在しないAPIメソッドを使⽤ 影響: 本番で初めてエラー発覚 # コード実装 client.describe_invalid_method()

    # 存在しない # ユニットテスト(モック) mock_client.describe_invalid_method = Mock() # → テストは通る # 本番環境 # → AttributeError
  27. 失敗14: テスト駆動の逆⾏ 39 問題: 正常なコードをテストに合わせて壊す 影響: 実装がロールバックするあるいは不正な状態になる • コード修正完了 →

    動作確認OK • テストコード修正 → テスト失敗 • 誤判断: 「コードをテストに合わせる」 • 結果: 正常だったコードが壊れる
  28. 失敗14: 対処法 40 • CLAUDE.mdにルールを明記 ◦ 実装→テストの順序を守る ◦ テスト失敗の原因を安易に推測しない •

    ⼈間が判断する ◦ テスト失敗時、AIの対応を鵜呑みにしない ◦ コードとテストのどちらが正しいか⼈間が判断 ◦ 「コードは正しいので、テストを修正して」と明確に指⽰
  29. 失敗15: 対処法 43 • CLAUDE.mdに確認事項を明記 ◦ ローカル vs CI/CD vs

    本番環境の違い ◦ 相対パス‧絶対パスの扱い ◦ パッケージ配布後の実⾏環境 ◦ 環境変数の有無 • 環境を指定して動作確認を指⽰ ◦ 「Lambda関数の環境で動作するか検証して」
  30. 失敗16: プロジェクト固有ルール無視 44 問題: 明記されたルールを忘れる 影響: ワークフロー破壊、作業失敗 # RELEASE.md: "CIの自動バージョン管理

    " # AI: package.json を手動で v1.2.0 に変更 # 結果: CI が誤って v1.3.0 に # メモリ: "awsumeを使用してAWSアクセス" # AI: awsume なしでアクセス → 失敗
  31. 失敗16: 対処法 45 • CLAUDE.mdに書いても忘れる ◦ 重要なルールは作業開始時に改めて明⽰的に指⽰ ◦ 「RELEASE.md読んで、バージョン管理⽅法を確認して」 ◦

    「awsumeでAWSアクセスしてる?」 • おかしいと感じたら即座に確認 ◦ 「本当にその⽅法で合ってる?ドキュメント確認して」 ◦ プロジェクト固有の慣習を都度リマインド
  32. 失敗17: 技術仕様の誤認 46 問題: 試⾏錯誤だけで仕様を確認しない 影響: 実現可能な機能を諦める # タスク: JSONPath

    → JSONata 変換 # AI: 修正 → エラー → 修正 → エラー # AI: 「JSONataはサポートされていません」(誤判断) # 実際: サポートされている(公式ドキュメント確認不足)
  33. 失敗17: 対処法 47 • AIが諦めたら疑う ◦ 「本当にサポートされていない?公式ドキュメント確認し て」 ◦ WebFetchやWebSearchで最新情報を調査させる

    ◦ 試⾏錯誤だけで判断させない • 具体例 ◦ 「JSONataはサポートされていません」→ 「AWS Step Functions公式ドキュメントで確認して」
  34. 失敗18: git操作で作業喪失 49 問題: 知らないうちに破壊的git操作で修正内容を消失 影響: 作業が完全に失われる(最も深刻) # 知らないうちに実行されている $

    git stash # コミット整理のため退避 → 復元忘れ $ git restore file.ts # 戻しすぎて修正分も消失 $ git checkout -- . # 未コミット変更を全破棄 # 結果: 復旧できず再実装
  35. 失敗18: 対処法 50 • 未コミット変更を作らせない ◦ 「作業ごとに都度コミットして」と指⽰ ◦ 知らないうちにstash/restoreされることがあるので注意 •

    コミット整理のワークフロー # 原則AIに都度コミットさせる # 整理する段階で以下を実行(ミスしても backup-before-reset から復元可能) $ git branch backup-before-reset $ git reset --soft HEAD~3 # AIに改めて適切な粒度で整理させる 「未コミットファイルを確認し、論理的な単位でコミットして」 # ※ rebase -i, add -p などの対話的操作は苦手
  36. 失敗19: ファイル内容喪失 51 問題: 誤った⼿順でファイル削除 → 内容忘却 影響: コード内容の完全喪失、復元不可能 #

    ❌ 危険な手順 $ rm old-file.ts # 削除 # → オートコンパクション発動 # → コード内容を全て忘れる # ✅ 安全な手順 $ cp old-file.ts new-file.ts # 作成 # 内容を移動・修正 $ rm old-file.ts # 削除
  37. 失敗19: 対処法 52 • 未コミットファイルを作らない ◦ 新規ファイル作成後はすぐ「コミットして」 ◦ ファイル削除を伴う作業前に「まずコミットして」 •

    ※現実的には ◦ 削除挙動を事前に⽌めるのは困難(常に監視できない) ◦ 起きた後の復元も未コミットなら不可能 ◦ Git履歴に残すことが唯⼀の保険
  38. 失敗20: 実装とドキュメントの乖離 53 問題: 説明と実装が⼀致しない 影響: デバッグ困難、信頼性の低下 # 報告: "デバッグログを追加しました

    " # 実際: ログが全く出ていない # 報告: "完全に機能しています " # 実際: まだ完成していません # ドキュメント: "3つのオプション" # 実装: 5つのオプションが存在
  39. 失敗20: 対処法 54 • 「完了」を信じない ◦ AIの報告を鵜呑みにせず、⾃分で仕様書と実装を照合 ◦ 「仕様書の◦◦項⽬、本当に実装されてる?該当コード⾒ せて」

    ◦ 「テストは全部パスしている?」 • 繰り返しチェックさせる ◦ 「ドキュメントと実装が⼀致しているか確認して」 ◦ 各機能ごとに照合を繰り返す ◦ 疑わしい箇所は動作確認
  40. 失敗から学んだこと 55 20のパターンを通じて⾒えてきたもの • AIの現実を知る ◦ メモリだけでは不⼗分、都度の指⽰が必要 ◦ Git履歴が唯⼀の保険 •

    ⼈間が主導する ◦ おかしいと思ったら即座に⽌める、軌道修正 ◦ ファクトチェックの習慣、盲信しない • 明確に伝える ◦ 曖昧さを排除、具体的な指⽰