name: code-refactor description: Martin Fowler の方法論に基づく体系的なコードリファクタリング。ユーザーがコードのリファクタリング、コード構造の改善、技術的負債の削減、レガシーコードのクリーンアップ、コードスメルの解消、コード保守性の向上を求めた際に使用する。本スキルは、リサーチ・計画・安全な段階的実装からなる段階的アプローチを案内する。

Martin Fowler 著『Refactoring: Improving the Design of Existing Code』(第 2 版) に基づくコードリファクタリングへの体系的アプローチ。本スキルは、テストに支えられた安全で段階的な変更を重視する。

"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure." — Martin Fowler

中核となる原則

  1. 振る舞いの保全: 外部から見える振る舞いは変えてはならない
  2. 小さなステップ: テスト可能な微小な変更を積み重ねる
  3. テスト駆動: テストはセーフティネットである
  4. 継続的: リファクタリングは一度きりの作業ではなく継続的に行う
  5. 協調的: 各フェーズでユーザーの承認が必要

ワークフロー概要

Phase 1: Research & Analysis
    ↓
Phase 2: Test Coverage Assessment
    ↓
Phase 3: Code Smell Identification
    ↓
Phase 4: Refactoring Plan Creation
    ↓
Phase 5: Incremental Implementation
    ↓
Phase 6: Review & Iteration

フェーズ 1: リサーチと分析

目的

ユーザーへの確認事項

開始前に次の点を明確化する。

  1. 範囲: どのファイル/モジュール/関数をリファクタリングするのか?
  2. 目標: 何を解決したいのか?(可読性、性能、保守性)
  3. 制約: 変更してはいけない領域はあるか?
  4. 時間的圧力: 他作業のブロッカーになっているか?
  5. テスト状況: テストは存在するか?パスしているか?

アクション

出力

ユーザーへの提示内容:


フェーズ 2: テストカバレッジの評価

なぜテストが重要か

"Refactoring without tests is like driving without a seatbelt." — Martin Fowler

テストは安全なリファクタリングを可能にする鍵となる要素である。テストがなければ、バグを混入させるリスクがある。

評価ステップ

  1. 既存テストの確認

    # テストファイルを探す
    find . -name "*test*" -o -name "*spec*" | head -20
    
  2. 既存テストの実行

    # JavaScript/TypeScript
    npm test
    
    # Python
    pytest -v
    
    # Java
    mvn test
    
  3. カバレッジの確認(可能な場合)

    # JavaScript
    npm run test:coverage
    
    # Python
    pytest --cov=.
    

判断ポイント: ユーザーへの確認

テストが存在し、かつパスしている場合:

テストが不足、または不完全な場合: 次の選択肢を提示する。

  1. 先にテストを書く(推奨)
  2. リファクタリング中に段階的にテストを追加する
  3. テストなしで進める(リスクあり、ユーザーの明示的同意が必要)

テストが失敗している場合:

テスト作成のガイドライン(必要時)

リファクタリング対象の各関数について、以下をテストでカバーする。

「red-green-refactor」サイクルを用いる。

  1. 失敗するテストを書く(red)
  2. パスさせる(green)
  3. リファクタリングする

フェーズ 3: コードスメルの特定

コードスメルとは?

コードに潜むより深い問題の症状である。バグそのものではないが、コード改善の余地を示す指標となる。

よくチェックすべきコードスメル

完全なカタログは references/code-smells.md を参照。

クイックリファレンス

スメル 兆候 影響
Long Method(長すぎる関数) メソッドが 30〜50 行を超える 理解、テスト、保守が困難
Duplicated Code(重複したコード) 同じロジックが複数箇所に存在 バグ修正を複数箇所で行う必要がある
Large Class(巨大なクラス) 責務が多すぎるクラス 単一責任原則に違反
Feature Envy(機能の横恋慕) 他クラスのデータを多く使用するメソッド カプセル化が不十分
Primitive Obsession(プリミティブ型への執着) オブジェクト化すべき所をプリミティブで多用 ドメイン概念が欠落
Long Parameter List(長すぎるパラメータリスト) パラメータが 4 個以上 正しく呼び出すのが困難
Data Clumps(データの群れ) 同じデータ項目が常に一緒に現れる 抽象化が欠落
Switch Statements(スイッチ文) 複雑な switch / if-else の連鎖 拡張が困難
Speculative Generality(投機的一般化) 「念のため」のコード 不要な複雑さ
Dead Code(デッドコード) 使われていないコード 混乱と保守負担

分析ステップ

  1. 自動分析(スクリプトが利用可能な場合)

    python scripts/detect-smells.py <file>
    
  2. 手動レビュー

    • コードを体系的に読み進める
    • 各スメルを場所と深刻度とともに記録する
    • 影響度別に分類する(Critical / High / Medium / Low)
  3. 優先順位付け 次のようなスメルに注力する。

    • 現在の開発をブロックしているもの
    • バグや混乱を引き起こしているもの
    • 変更頻度が高いコードパスに影響するもの

出力: スメルレポート

ユーザーへの提示内容:


フェーズ 4: リファクタリング計画の作成

リファクタリング技法の選定

各スメルに対して、カタログから適切なリファクタリング技法を選ぶ。

完全な一覧は references/refactoring-catalog.md を参照。

スメル別の推奨リファクタリング

コードスメル 推奨リファクタリング
Long Method(長すぎる関数) メソッドの抽出、Replace Temp with Query
Duplicated Code(重複したコード) メソッドの抽出、Pull Up Method、Form Template Method
Large Class(巨大なクラス) クラスの抽出、Extract Subclass
Feature Envy(機能の横恋慕) Move Method、Move Field
Primitive Obsession(プリミティブ型への執着) Replace Primitive with Object、Replace Type Code with Class
Long Parameter List(長すぎるパラメータリスト) パラメータオブジェクトの導入、Preserve Whole Object
Data Clumps(データの群れ) クラスの抽出、パラメータオブジェクトの導入
Switch Statements(スイッチ文) ポリモーフィズムによる条件記述の置き換え
Speculative Generality(投機的一般化) Collapse Hierarchy、Inline Class、デッドコードの削除
Dead Code(デッドコード) デッドコードの削除

計画の構成

templates/refactoring-plan.md のテンプレートを使用する。

各リファクタリングごとに次の項目を埋める。

  1. 対象: 何を変更するか
  2. スメル: どの問題に対処するか
  3. リファクタリング: どの技法を適用するか
  4. 手順: 細かいマイクロステップ
  5. リスク: 何が失敗しうるか
  6. ロールバック: 取り消す方法

段階的アプローチ

重要: リファクタリングはフェーズに分けて段階的に導入する。

フェーズ A: クイックウィン(低リスク、高価値)

フェーズ B: 構造改善(中リスク)

フェーズ C: アーキテクチャ変更(高リスク)

判断ポイント: ユーザーへの計画提示

実装前に:


フェーズ 5: 段階的な実装

ゴールデンルール

"Change → Test → Green? → Commit → Next step"

実装のリズム

各リファクタリングステップで:

  1. 事前チェック

    • テストがパスしている(green)
    • コードがコンパイルできる
  2. 小さな変更を 1 つだけ行う

    • カタログのメカニクスに従う
    • 変更は最小限に保つ
  3. 検証

    • 直ちにテストを実行
    • コンパイルエラーがないか確認
  4. テストがパス(green)した場合

    • 説明的なコミットメッセージでコミット
    • 次のステップへ進む
  5. テストが失敗(red)した場合

    • 直ちに STOP
    • 変更を取り消す
    • 何が起きたかを分析する
    • 不明な場合はユーザーに確認する

コミット戦略

各コミットは次の性質を満たすこと。

コミットメッセージ例:

refactor: Extract calculateTotal() from processOrder()
refactor: Rename 'x' to 'customerCount' for clarity
refactor: Remove unused validateOldFormat() method

進捗報告

サブフェーズごとに、ユーザーへ次を報告する。


フェーズ 6: レビューと反復

リファクタリング後チェックリスト

メトリクス比較

リファクタリング前後で複雑度解析を実施する。

python scripts/analyze-complexity.py <file>

改善点を提示する。

ユーザーレビュー

最終結果を提示する。

次のステップ

ユーザーと議論する。


重要なガイドライン

STOP してユーザーに相談すべきタイミング

次の場合、必ず一旦止まりユーザーに相談する。

安全のためのルール

  1. テストなしでリファクタリングしない(ユーザーが明示的にリスクを受容しない限り)
  2. 大きな変更を一度にしない - 微小なステップに分割する
  3. 各変更後のテスト実行を省略しない
  4. テスト失敗時は続行しない - 修正かロールバックを先に行う
  5. 思い込みで進めない - 疑問があれば確認する

やってはいけないこと


クイックスタート例

シナリオ: 重複を含む長い関数

Before:

function processOrder(order) {
  // 150 行のコードに以下が混在:
  // - 重複したバリデーションロジック
  // - インラインの計算処理
  // - 複数の責務
}

リファクタリング手順:

  1. processOrder() に対するテストの存在を確認
  2. バリデーションを validateOrder() に抽出
  3. テスト - パスすること
  4. 計算を calculateOrderTotal() に抽出
  5. テスト - パスすること
  6. 通知を notifyCustomer() に抽出
  7. テスト - パスすること
  8. レビュー - processOrder() は明確な 3 関数の調整役となる

After:

function processOrder(order) {
  validateOrder(order);
  const total = calculateOrderTotal(order);
  notifyCustomer(order, total);
  return { order, total };
}

参考文献

スクリプト

バージョン履歴