Back to Blog
development·

Claude Codeで巨大コードベースをリファクタする手順|段階的アプローチ

Claude Codeを活用した巨大コードベースのリファクタリング手順を段階的に解説。分析・計画・実行・検証の4フェーズで安全にコード品質を改善する方法と、CLAUDE.mdによるルール定義、失敗パターンの回避策を紹介します。

#Claude Code#Claude Code 実践#リファクタリング
Claude Codeで巨大コードベースをリファクタする手順|段階的アプローチ

リファクタリングは「やるべきだと全員がわかっているのに、なかなか着手できない」技術課題の代表格です。影響範囲の把握に数日、実行にさらに数日、テストの修正に数日 — この見積もりを聞いた時点でチケットがバックログの奥に沈んでいく光景は珍しくありません。

Claude Codeはリポジトリ全体を文脈として読み取り、依存関係を追跡し、段階的な変更計画を立てて実行できるエージェントです。本記事では、Claude Codeを使ったリファクタリングの段階的アプローチを、実際のプロンプト例とともに実務で再現できるレベルで解説します。Claude Codeの基本についてはClaude Code完全ガイドを参照してください。

結論 — Claude Codeはリファクタリングの「分析と機械的変更」を圧縮する

リファクタリングにおけるClaude Codeの最大の価値は、影響範囲の分析と機械的な変更作業を大幅に圧縮できる点にあります。「この関数はどこから呼ばれているか」「この型を変えたら何箇所に影響するか」「100ファイル以上にまたがるリネーム」— こうした作業に費やしていた時間が劇的に短縮されます。

ただし、「何をどう変えるか」の設計判断は人間の責任です。Claude Codeに丸投げするのではなく、分析 → 計画 → 実行 → 検証の4フェーズで段階的に進めることが、安全なリファクタリングの鍵になります。

なぜClaude Codeがリファクタリングに適しているか

従来のリファクタリングでは、IDEのリネーム機能や正規表現置換に頼る場面が多くありました。しかし、これらのツールは構文的な置換にとどまり、「この関数の責務を分割する」「このモジュールの依存関係を整理する」といった設計レベルの変更には対応できません。

Claude Codeが異なるのは、以下の点です。

  • リポジトリ全体を文脈として保持できる: 1つのファイルだけでなく、関連するファイル群を横断的に把握した上で変更を計画します
  • 自然言語で意図を伝えられる: 「このクラスの責務を分割して」と指示すれば、具体的な分割案を提案してくれます
  • テスト実行まで一貫して行える: 変更後にテストを走らせ、失敗したテストの原因を分析し、修正まで自律的に進められます
  • Gitの差分を理解して操作できる: 変更をコミット単位で区切り、レビューしやすい粒度を維持します

ここで重要なのは、Claude Codeは「魔法の杖」ではないということです。800行のファイルを渡して「きれいにして」と言っても、意図通りの結果にはなりません。段階的なアプローチが不可欠です。

段階的アプローチ — 4フェーズで安全に進める

フェーズ1: 分析 — 現状を正確に把握する

最初にClaude Codeへ依頼するのは、コードの現状分析です。いきなり変更を指示するのではなく、まず全体像を把握させます。

このリポジトリのsrc/services/ディレクトリを分析してほしい。
以下の観点で整理して:

1. 各ファイルの行数と責務の概要(1行で)
2. 循環依存の有無(あれば具体的なファイルパスを提示)
3. 50行を超える関数の一覧(ファイルパス・関数名・行数)
4. exportされているが外部から参照されていない関数
5. 同一ロジックが3箇所以上重複しているパターン

分析結果のみ出力して、コードへの変更は行わないでほしい。

ここでのポイントは「コードへの変更は行わないでほしい」と明示することです。この一文がないと、Claude Codeは分析結果をもとに「ついでに修正しておきました」と勝手に変更を入れることがあります。

分析結果の出力例を見てみましょう。

## 分析結果: src/services/

### ファイル一覧と責務
| ファイル | 行数 | 責務 |
|---------|------|------|
| user-service.ts | 382行 | 認証・プロフィール更新・通知の3責務が混在 |
| order-service.ts | 245行 | 注文処理(適切な範囲) |
| payment-service.ts | 567行 | 決済処理・請求書生成・返金処理 |
| notification-service.ts | 89行 | メール・Slack通知(適切な範囲) |

### 循環依存
- user-service.ts → payment-service.ts → user-service.ts
  (getUserBalance が相互参照している)

### 50行超の関数(3件)
- user-service.ts: processUserRegistration (78行)
- payment-service.ts: handleRefund (92行)
- payment-service.ts: generateInvoice (65行)

この段階では分析結果を受け取るだけです。チームで共有し、リファクタリングの優先度を議論する材料として活用します。

4フェーズの段階的アプローチ

フェーズ2: 計画 — 変更方針を合意する

分析結果をもとに、具体的な変更計画を立てます。ここでもClaude Codeに計画の素案を作らせ、人間がレビューして方針を固めます。

src/services/user-service.tsが382行あり、以下の3つの責務が混在している:
- ユーザー認証(signup, login, resetPassword)
- プロフィール更新(updateProfile, uploadAvatar)
- 通知設定(updateNotificationPrefs, getNotificationHistory)

以下の方針で分割計画を立ててほしい:
- 1ファイル1責務で3ファイルに分割
- 共通で使われるユーティリティがあれば別ファイルに抽出
- 既存のテスト(user-service.test.ts)が全てパスする状態を維持
- 外部からのインポートパスが変わるファイルの一覧を洗い出す
- 各ステップの実行順序と、ステップ間の依存関係を明示する

計画だけ提示して、まだ実行はしないでほしい。

「計画だけ提示して実行はしないでほしい」と明示的に指示することがポイントです。Claude Codeは指示がなければ実行に移ることがあるため、フェーズを区切って進めます。

計画が出力されたら、以下の観点でレビューします。

  • 分割の粒度は適切か(細かすぎないか、粗すぎないか)
  • 各ステップの順序に論理的な矛盾がないか
  • テストの移動・分割計画は含まれているか
  • 外部への影響範囲は許容できるか

フェーズ3: 実行 — 小さな単位で変更する

計画に合意したら、変更を小さな単位で実行します。一度に全てを変更するのではなく、1つの責務の分離ごとにコミットを区切るのが安全です。

計画のステップ1を実行してほしい。

対象: user-service.ts から認証関連の関数を auth-service.ts に分離する
- signup, login, resetPassword, validateToken を移動
- 共通のユーティリティ(hashPassword, generateToken)は user-utils.ts に抽出
- user-service.ts からは auth-service.ts を re-export して、既存のインポートを壊さない
- 完了したら pnpm test を実行して結果を教えてほしい

このステップだけ実行して、ステップ2以降はまだ実行しないでほしい。

この粒度で進めることで、テストが失敗した場合の原因特定が容易になります。「全部変えたけどテストが50件落ちた」という状況と「認証の分離だけでテストが3件落ちた」という状況では、デバッグの難易度がまるで違います。

フェーズ4: 検証 — テストと型チェックで担保する

各ステップの実行後、Claude Codeにテストと型チェックを走らせて結果を確認します。

ステップ1の変更について、以下を確認してほしい:

1. pnpm test を実行して全テストがパスするか
2. pnpm typecheck を実行して型エラーがないか
3. auth-service.ts から user-service.ts への循環参照がないか確認
4. git diff --stat で変更ファイルの一覧を見せてほしい

テストが失敗した場合は、原因分析と修正をそのまま依頼できます。ここでClaude Codeが力を発揮するのは、「テスト失敗 → 原因特定 → 修正 → 再テスト」のループを高速に回せる点です。

具体的なシナリオ: 100ファイル以上にまたがるリネーム

UserProfile という型名を Account にリネームしたい。100ファイル以上で使われている」— こうしたシナリオでClaude Codeの真価が発揮されます。

IDEのリネーム機能では、型名・変数名・ファイル名・コメント・テストのdescription文まで一括で対応することは困難です。Claude Codeなら以下のように指示できます。

UserProfile という型名を Account にリネームしたい。
以下のスコープで全て変更してほしい:

1. 型定義(interface UserProfile → interface Account)
2. 型の参照(UserProfile を使っている全箇所)
3. 変数名(userProfile → account, userProfiles → accounts)
4. ファイル名(user-profile.ts → account.ts, user-profile.test.ts → account.test.ts)
5. インポートパスの更新
6. テストのdescription文("UserProfile" → "Account")
7. コメント・JSDoc内の参照

まず影響範囲を洗い出して一覧を見せてほしい。
変更は承認後に実行する。

Before(リネーム前のファイル構成):

src/
├── types/user-profile.ts          # interface UserProfile
├── services/user-profile-service.ts
├── components/UserProfileCard.tsx
├── hooks/useUserProfile.ts
└── __tests__/user-profile.test.ts

After(リネーム後のファイル構成):

src/
├── types/account.ts               # interface Account
├── services/account-service.ts
├── components/AccountCard.tsx
├── hooks/useAccount.ts
└── __tests__/account.test.ts

ここでの注意点は、一度に全部変更するのではなく、段階的に進めることです。

  1. 型定義のリネーム + 型の参照更新(コンパイルが通る状態を維持)
  2. ファイル名のリネーム + インポートパスの更新
  3. 変数名の更新
  4. テスト・コメントの更新

各段階でテストを実行し、問題がないことを確認してから次に進みます。

CLAUDE.mdによるリファクタリングルール定義

CLAUDE.mdでリファクタリングルールを定義する

チームでリファクタリングを進める場合、CLAUDE.md にルールを記述しておくと品質が安定します。

# リファクタリングルール

## ファイルサイズ
- 1ファイル400行を推奨上限、800行を絶対上限とする
- 超過しているファイルは責務分割の候補

## 関数サイズ
- 1関数50行を上限とする
- 超過している場合は小さい関数に分割する

## ネスト
- ネストの深さは3レベルまで
- 超過している場合は早期returnまたは関数抽出で平坦化する

## 変更時の制約
- リファクタリングと機能追加を同じコミットに混ぜない
- 既存テストが全てパスする状態を維持する
- 外部APIのインターフェースは変更しない(破壊的変更は別チケット)
- git add . は使用禁止。変更したファイルを個別に git add する

## リファクタリングの進め方
- まず分析結果を提示し、変更の承認を得てから実行する
- 1コミット1責務で変更を分割する
- 各コミット後に pnpm test && pnpm typecheck を実行して問題がないことを確認する

この定義があることで、Claude Codeは「この関数は55行あるので分割が必要です」「ネストが4レベルに達しているので早期returnを導入します」といった判断を自律的に行えるようになります。

実際の効果として大きいのは、複数人がClaude Codeを使ってリファクタリングする場合の一貫性の担保です。CLAUDE.mdがなければ、Aさんのセッションでは300行のファイルが放置され、Bさんのセッションでは100行で分割される — という品質のばらつきが生じます。

3つの失敗パターンと回避策

パターン1: 一度に大きく変えすぎる

症状: 「このモジュール全体をリファクタリングして」と指示した結果、20ファイルが同時に変更され、テストが30件失敗する。どの変更が原因か特定できず、結局 git checkout . で全部巻き戻すことになる。

回避策: 1セッションで1モジュールの1つの改善に絞り、コミットを区切りながら進めます。「このファイルのこの関数を分割して」のレベルまで指示を具体化すると安全です。

# Bad — 範囲が広すぎる
このリポジトリ全体のコード品質を改善して

# Good — 範囲が明確
src/services/payment-service.ts の handleRefund 関数(92行)を、
バリデーション・処理・後処理の3つの関数に分割してほしい

パターン2: テストなしでリファクタリングする

症状: テストカバレッジが低いモジュールをリファクタリングした結果、動作が変わっていることに本番デプロイ後に気づく。

回避策: テストがないコードは、リファクタリングの前にテストを追加するのが鉄則です。Claude Codeにテスト追加から依頼するのが有効です。

src/services/payment-service.ts の handleRefund 関数に対して、
リファクタリング前の動作を担保するテストを作成してほしい。

以下のケースをカバーしてほしい:
- 正常な返金処理
- 返金額が注文額を超える場合のエラー
- 決済プロバイダのAPI障害時の挙動
- 二重返金の防止

テストが全てパスすることを確認してから、
このテストをコミットしてほしい(リファクタリングとは別コミットで)。

この手順を踏むことで、リファクタリング後にテストが失敗すれば「動作が変わった」とすぐに検知できます。

パターン3: リファクタリングと機能追加を同時に行う

症状: 「リファクタリングしつつ、ついでにこの機能も追加しておいて」と依頼した結果、PRが巨大化し、レビュアーが変更の意図を理解できない。バグが混入しても、リファクタリングが原因なのか機能追加が原因なのか判別できない。

回避策: リファクタリングのコミットと機能追加のコミットは必ず分離します。理想的にはPRレベルで分けるべきです。

# Bad
この関数をリファクタリングして、ついでにキャッシュ機能も追加して

# Good(2つのセッションに分ける)
セッション1: この関数をリファクタリングしてコミットまで
セッション2: リファクタリング後のコードにキャッシュ機能を追加してコミットまで

よくある質問

よくある質問

まとめ — 段階的アプローチで安全にコード品質を改善する

Claude Codeを使ったリファクタリングの要点は、分析 → 計画 → 実行 → 検証の4フェーズを明確に区切り、小さな単位で進めることです。

重要なのは、Claude Codeの役割を正しく理解することです。Claude Codeは「影響範囲を高速に分析し、機械的な変更を正確に実行する」ことに優れています。一方で、「何をどう変えるか」の設計判断は人間が行うべきです。この役割分担を意識することで、リファクタリングの品質と安全性を両立できます。

CLAUDE.mdによるルール定義と段階的な進め方を組み合わせることで、これまで「やるべきだが手が出せない」と放置されていた技術的負債の返済を、現実的なペースで進められるようになります。

koromo からの提案

AIツールの導入判断は、突き詰めると「投資対効果が合うか」「リスクを管理できるか」「事業にどう効くか」の3点に帰着します。koromo では、この判断に必要な材料を整理するところからご支援しています。

以下のような状況にある方は、まず現状の整理だけでも前に進むきっかけになります。

  • AIで開発や業務を効率化したいが、自社に合う方法がわからない
  • 社内にエンジニアがいない / 少人数で、AI導入の進め方に見当がつかない
  • 外注先の開発会社にAI活用を提案したいが、何を求めればいいか整理できていない
  • 「AIを使えばコスト削減できるはず」と感じているが、具体的な試算ができていない

ツールを使った上で相談したい方はお問い合わせフォームから「Claude Codeを活用したリファクタリングの相談」とご記載ください。初回の壁打ち(30分)は無料で対応しています。

関連記事

本記事の更新方針: 本記事は定期的に内容を見直しています。記事内の判断軸・運用パターンは執筆時点での koromo の実務的知見に基づくものであり、個別環境での効果を保証するものではありません。仕様の最新情報は必ず Anthropic 公式ドキュメント をご確認ください。

Related Articles