TL;DR
- Claude Codeに「一気にやらせる」と想定外ファイルまで変更されてビルドが壊れるリスクがある(経験則)
- 安全策はスコープ制御・段階的適用・テスト保護・rollback戦略の4軸
- 「1ファイル → テスト → 確認 → 次ファイル」の確認ループが最も安全な進め方
- git commitは「リファクタリング単位」ではなく「動作確認単位」で刻む
- 本記事のプロンプトテンプレートをそのままコピーして使えば即日適用可能
📚 シリーズ: Claude Code シリーズ:環境設定から実践まで
はじめに:「AIに一気にやらせる」の罠
Claude Codeを使い始めて1〜3ヶ月が経った頃、多くのエンジニアが同じ失敗をします。
「このプロジェクト全体のUser型をAPIUser型に変更して」
実行してみると、想定外の場所まで変更されてTypeScriptのコンパイルエラーが100件超。ビルドが壊れ、どこが変わったのか追うだけで1時間——。
これは Claude Code の問題ではありません。マルチファイルリファクタリングを「一気に」依頼したことが問題です。
人間でも同じです。「このシステム全体のデータモデルを変えてください」と言われたら、慎重なエンジニアは必ず「どのファイルから?」「テストはどうする?」「rollbackの方法は?」と確認します。
Claude Code に対しても同じ設計が必要です。本記事では、4つの軸でClaude Codeを制御しながらマルチファイルリファクタリングを安全に進める手順を解説します。
マルチファイルリファクタリングの4つのリスク
Claude Code で大規模変更を行う際、以下の4つのリスクを認識しておく必要があります。
| リスク | 具体的な症状 | 発生頻度 |
|---|---|---|
| スコープ過拡大 | 指定外ファイルへの変更、テストファイルの書き換え | 高 |
| 中間状態の蓄積 | 変更が半端な状態でビルドが通らなくなる | 中 |
| 依存関係の見落とし | 型変更の影響が波及して別モジュールが壊れる | 高 |
| rollback困難 | 大きな変更をひとまとめにしたため、どこに戻ればいいかわからない | 中 |
これらのリスクは適切なプロセス設計で大幅に軽減できます。
1. スコープ制御:変更範囲をClaude Codeに明示する
アンチパターン vs 安全パターン
アンチパターン(やってはいけない)
# NG: スコープが曖昧
「プロジェクト全体のUser型をAPIUser型に変更して」
安全パターン
# OK: 変更対象ファイルを明示的に指定
「以下のファイルのみを対象に、User型をAPIUser型に変更してください。
変更対象: src/services/userService.ts, src/api/userController.ts
変更禁止: テストファイル(*.test.ts, *.spec.ts)、型定義ファイル(types/*.d.ts)
変更後はTypeScriptのコンパイルが通ることを確認してください。」
CLAUDE.md / AGENTS.md によるスコープ固定
プロジェクトルートに以下のような CLAUDE.md を配置することで、Claude Code のデフォルト動作を制限できます(公式ドキュメント参照)。
## リファクタリング時の制約
- テストファイル(*.test.ts, *.spec.ts)は変更禁止
- package.json, tsconfig.json は明示的に指定されない限り変更禁止
- 変更後は必ず `pnpm tsc --noEmit` でコンパイルエラーがないことを確認
- 一度のセッションで変更するファイルは最大3件まで
この設定により、Claude Code は自律的にスコープを守るようになります。
ファイルリストを事前に提示する
「以下のファイルを変更する前に、影響を受ける可能性がある他のファイルを
リストアップしてください。その後、私が承認したファイルのみ変更します。
対象: src/models/User.ts の User インターフェース定義」
「変更してください」の前に「影響範囲を教えてください」を挟むことが重要です。このひと手間が大きな事故を防ぎます。
2. 段階的適用:「1ファイル→テスト→次ファイル」ループ設計
マルチファイルリファクタリングの核心は確認ループの設計です。AIとのペアプログラミングでも述べているように、人間とAIの協働では「確認ポイント」の設計が最も重要です。
確認ループの基本フロー
┌─────────────────────────────────────┐
│ 1. 影響範囲のリストアップ(Claude Code) │
│ ↓ │
│ 2. 変更対象ファイルを1件選択(人間) │
│ ↓ │
│ 3. 1ファイルのみ変更(Claude Code) │
│ ↓ │
│ 4. コンパイル確認・テスト実行(人間/AI) │
│ ↓ │
│ 5. 問題なければ git commit(人間) │
│ ↓ │
│ 6. 次のファイルへ(2に戻る) │
└─────────────────────────────────────┘
プロンプトテンプレート:段階的適用
「以下のリファクタリングを段階的に進めます。
一度に変更するのは1ファイルのみとし、私が「次に進んでください」と
言うまで次のファイルには手をつけないでください。
リファクタリング内容: UserService のメソッド名を camelCase から snake_case に統一
対象ファイル一覧(変更順):
1. src/services/UserService.ts
2. src/api/UserController.ts
3. src/utils/userHelpers.ts
まず1番のファイルのみ変更してください。
変更後、変更箇所の一覧を提示してください。」
この「1ファイルずつ」の原則は、変更が複雑になるほど重要です。10ファイルを一気に変更するよりも、1ファイルずつ確認しながら進める方が、トータルの作業時間は短くなります(経験則)。
3. テスト保護:リファクタリング前のテスト整備チェックリスト
リファクタリングの安全網はテストです。Claude Code Hooks の活用と組み合わせることで、テストを自動的なセーフティネットとして機能させられます。
リファクタリング前チェックリスト
□ 変更対象ファイルのユニットテストが存在する
□ テストが現在 PASS している(グリーン状態)
□ テストカバレッジが主要なパスを網羅している(目安: 80%以上)
□ 統合テスト / E2Eテストが存在する場合、それらもパスしている
□ テストなしで進める場合、最低限のスモークテストを先に書いた
テストをセーフティネットとして活用するプロンプト
「UserService.ts をリファクタリングします。
変更前に現在のテスト全てが PASS していることを確認してください。
変更後も同じテストが PASS していることを確認してください。
テストが FAIL した場合は変更を中断し、原因を教えてください。
確認コマンド: pnpm test src/services/UserService.test.ts」
テストがない場合の対処
既存コードにテストがない場合、リファクタリング前に「特性テスト(Characterization Test)」を追加することを推奨します。
「UserService.ts をリファクタリングする前に、現在の動作を記述する
テストを追加してください。テストの目的は振る舞いの仕様化であり、
コードのクリーンアップではありません。
既存の動作をそのままテストとして書き出してください。」
4. Rollback戦略:git stash / feature branch / コミット粒度の指針
安全なリファクタリングには事前のrollback戦略が必要です。開発計画フェーズの設計で計画する際にもrollbackポイントの設計を組み込んでおきましょう。
3層のrollback設計
Layer 1: git stash(実験的変更の一時退避)
↓ 変更を捨てたい場合: git stash drop
↓ 変更を戻したい場合: git stash pop
Layer 2: feature branch(作業単位の分離)
↓ 失敗した場合: git checkout main && git branch -D feature/refactor-xxx
Layer 3: コミット粒度(細かいrollbackポイント)
↓ 特定の変更だけ戻す: git revert <commit-hash>
↓ あのポイントに戻る: git reset --hard <commit-hash>
feature branch の作業フロー
# 1. リファクタリング用ブランチを作成
git checkout -b refactor/user-type-migration
# 2. 1ファイルずつ変更・確認・コミット
git add src/services/UserService.ts
git commit -m "refactor(user): UserService の型を APIUser に変更"
# 3. 次のファイルへ進む(問題があれば git revert で戻せる)
git add src/api/UserController.ts
git commit -m "refactor(user): UserController の型を APIUser に変更"
git commitのタイミングと粒度の指針
| タイミング | コミットすべきか | 理由 |
|---|---|---|
| 1ファイル変更・テストPASS後 | する | rollbackポイントになる |
| 複数ファイル変更・未テスト | しない | 問題特定が困難になる |
| コンパイルエラーあり | しない | ビルドを壊したコミットは後処理が面倒 |
| 「とりあえず保存」 | WIPコミットで可 | git commit -m "WIP" 後で git rebase -i で整理 |
5. プロンプト例集
パターン1:関数移動
「以下の関数を src/utils/helpers.ts から src/utils/stringUtils.ts に移動してください。
移動する関数: formatUserName, truncateText, capitalizeFirst
移動元: src/utils/helpers.ts
移動先: src/utils/stringUtils.ts(ファイルが存在しない場合は新規作成)
移動後の作業:
1. helpers.ts の該当関数を削除
2. helpers.ts が使われている箇所で stringUtils.ts からのインポートに変更
3. TypeScript コンパイルエラーがないことを確認
一度に1つの関数のみ移動し、各ステップで確認を求めてください。」
パターン2:型変更(Before/After)
Before(危険なプロンプト)
# NG
「UserIdをstringからnumberに変更して」
After(安全なプロンプト)
# OK
「UserId の型を string から number に変更します。
変更の影響範囲を把握するため、まず以下のコマンドで参照箇所を列挙してください。
grep -rn "UserId" src/ --include="*.ts"
その後、私が変更対象ファイルを選択します。
一度に変更するのは1ファイルのみ、変更後はコンパイル確認を必須とします。」
パターン3:命名統一
「以下のリファクタリングを段階的に進めます。
目的: `getUserInfo` という命名を `fetchUserProfile` に統一する
(現在、同じ処理が異なる名前で実装されている)
手順:
1. `getUserInfo` の呼び出し箇所をすべてリストアップ
2. 各ファイルを1つずつ変更
3. 変更のたびに pnpm tsc --noEmit で確認
リストアップから始めてください。変更は私の指示を待ってください。」
6. 壊れやすいリファクタリングパターン Top5
AI コードレビューの品質管理の観点からも、以下のパターンは特に注意が必要です。
1. 型の広域変更(最も危険)
TypeScript の型定義ファイル(types.ts, *.d.ts)の変更は、プロジェクト全体に影響します。必ず影響範囲を事前に確認し、最後に変更することを推奨します。
2. インポートパスの変更
import { foo } from '../utils' を import { foo } from '@/utils' に変更するようなパスエイリアス移行は、一見シンプルに見えて影響範囲が広くなりがちです。
対処法:tsconfig.json の paths 設定を先に確認し、ファイルを1つずつ移行します。
3. 非同期処理のリファクタリング
コールバック → Promise → async/await の移行は、エラーハンドリングの変化を伴います。テストなしで進めると、エラーケースが見落とされるリスクがあります。
4. クラス → 関数コンポーネントへの移行(React)
状態管理の書き方が根本的に変わるため、1コンポーネントずつ完全に書き換えてテストすることが必要です。混在状態での動作確認を怠ると、ライフサイクルの差異でバグが生じます。
5. ディレクトリ構造の変更
ファイル移動はgitの追跡履歴に影響します。git mv を使って移動することで、履歴が保持されます。Claude Code に依頼する場合も git mv を明示的に指定してください。
「src/services/userService.ts を src/domain/user/service.ts に移動してください。
git mv コマンドを使い、履歴が保持されるようにしてください。
移動後、インポートパスを更新してください(変更ファイル一覧を先に提示)。」
FAQ
Q1. Claude Codeで大規模なリファクタリングを行う際の最大の注意点は?
最大の注意点はスコープの明示です。「プロジェクト全体を変えて」という指示は避け、「このファイルのこの関数のみ」という形で対象を絞り込みます。また、変更禁止ファイル(テスト、設定ファイルなど)を明示することも重要です。AGENTS.md/CLAUDE.md によるスコープ固定が最も効果的です。
Q2. マルチファイルにわたるリネームをClaude Codeで安全に行うには?
まず grep や TypeScript の参照検索で影響ファイル一覧を取得し、次にファイルを1つずつ変更・コンパイル確認・コミットのサイクルを繰り返します。IDEのリファクタリング機能(VS Code の「すべての参照の名前変更」)との組み合わせも有効です。
Q3. AIリファクタリング中にテストをどう活用すればよいか?
テストは変更前後の動作が同じことを保証するセーフティネットです。変更前にテストをグリーンにし、変更後も同じテストがグリーンであることを確認します。テストがない場合は、まず「特性テスト」を追加してから変更を始めてください。
Q4. Claude Codeがリファクタリングで失敗したときのrollback手順は?
3段階で対応します。1)git diff で変更内容を確認、2)git checkout <file> で特定ファイルのみ元に戻す、3)全体を戻す場合は git reset --hard HEAD または git stash pop(stashしていた場合)。feature branch で作業していれば、git checkout main に戻るだけで完全にリセットできます。
Q5. 「一気にやらせる」と何が具体的に問題になるのか?
主に3つの問題が発生します。1)変更箇所が多すぎてデバッグ困難になる(どのファイルのどの変更が原因か特定できない)、2)コンパイルエラーが連鎖して、エラーの根本原因が埋もれる、3)rollbackの粒度が粗くなる(元に戻すと全部の変更が失われる)。小さく区切ることは遠回りに見えて、実際には最速の方法です。
👉 シリーズ全体像: Claude Code 環境セットアップガイド
まとめ:4軸で制御するClaude Codeリファクタリング
Claude Codeは適切に制御すれば、大規模リファクタリングの強力なパートナーになります。重要なのは以下の4軸です。
| 軸 | 具体的なアクション |
|---|---|
| スコープ制御 | 変更対象ファイルと変更禁止ファイルを明示する |
| 段階的適用 | 1ファイルずつ変更・確認・コミットのループを守る |
| テスト保護 | 変更前後でテストがグリーンであることを確認する |
| rollback戦略 | feature branchを切り、コミット粒度を細かく保つ |
これらのプロセスを習慣にすれば、「AIに任せたら壊れた」という失敗は大幅に減ります。
次のステップとして、以下の記事も参考にしてください。
- AIとのペアプログラミング実践パターン — コンテキスト設計・セッション引き継ぎの具体的な方法
- Claude Code Hooksの実践活用 — 変更前後の自動チェックをHooksで組み込む方法
- AI駆動の開発計画 — リファクタリングを安全に計画する上流工程のアプローチ
