広告枠を募集中 ご相談ください

Mutable.ai VS Code 拡張機能と Auto Edit で複雑な関数を自然言語リファクタリングする実践ガイド

365Finds Editorial
Wiki 記事 11,430 本収録

あなたの AI で 365 Wiki を使う

下のプロンプトをコピーして、普段使っている AI に貼り付け、そのまま質問してください。

完全版 Skill をダウンロード

まずはプロンプトでお試しください。よく使う場合は完全版 365Wiki Skill をインストールすると、毎回貼り付ける必要がありません。普段使う AI がなければ、Gemini や Microsoft Copilot のウェブ版でも使えます。

ソフトウェアの長期保守において、肥大化し複雑化したレガシー関数のリファクタリングは、エンジニアにとって最も神経を使う作業の一つです。深い条件分岐のネスト、コールバック地獄、暗黙の状態変更、そして古い「ゾンビコード」が混在する数百行の関数を手作業で1行ずつ書き直そうとすると、構文エラーの混入やスコープ破壊、予期せぬリグレッション(先祖返り・不具合)を招きやすくなります。

Mutable.ai は、この課題を解決するために Visual Studio Code 拡張機能へ Auto Edit(自動編集) を実装しました。カーソル位置から数行先を予測するだけの単なるコード補完や、ブラウザとエディタの間でコードをコピー&ペーストしなければならない外部チャットとは異なり、Auto Edit はエディタ内で完結する自然言語リファクタリングエンジンです。開発者は対象コードを選択し、日本語や英語などの自然言語で指示を与えるだけで、プロジェクト全体の文脈を考慮した安全かつアトミックなコード改善を実行できます。


1. Auto Edit と従来のコード補完・AI チャットの違い

AI 開発支援ツールの操作形態は、大きく以下の2つに分かれていました。

  1. インライン補完(ゴーストテキスト): GitHub Copilot に代表される形式で、カーソル位置から直後のコードを推測します。定型コードの生成には有用ですが、関数全体の構造改革や複数箇所にまたがる依存関係の整理には対応できません。
  2. サイドバー・チャット: チャットパネルで AI にリファクタリング案を尋ねる形式です。しかし、コードをパネルに貼り付け、生成結果をエディタへ手動で移植する必要があり、集中力(フロー状態)が途切れ、細部の不整合も見落としがちになります。

Mutable.ai の Auto Edit は、自然言語による指示と IDE のネイティブ機能を統合しています。


2. VS Code で Auto Edit を呼び出す3つの方法

Mutable.ai 拡張機能では、作業の流れに合わせて以下の3系統のエントリポイントが用意されています。

呼び出し方法アクセス手順最適なユースケース
Code Lens関数宣言の直上に表示される Auto Edit ラベルをクリック単一の関数、メソッド、またはクラスの集中リファクタリング
ステータスバー画面最下部のステータスバーにある Mutable.ai アイコンをクリックグローバルコマンドの呼び出しや拡張機能の状態確認
コンテキストメニュー選択範囲またはファイルツリーを右クリックし Mutable.ai: Auto Edit を選択複数ブロックの編集やモジュール単位の変更

呼び出しを行うと、選択コードの直上にフローティング入力ボックスが表示され、自然言語の指示待ち状態になります。


3. 複雑な関数をリファクタリングする標準ワークフロー

Auto Edit を用いた実践的なリファクタリング手順は以下の5ステップです。

[対象の複雑な関数]
       │
       ▼
[ステップ 1: 範囲選択] ──► [ステップ 2: Auto Edit 起動] ──► [ステップ 3: 明確なプロンプト入力]
                                                                        │
                                                                        ▼
[ステップ 5: 確定・検証] ◄── [ステップ 4: エディタ内 Diff 確認] ◄── [AI による文脈合成]

ステップ 1: 対象関数のスコープを絞る

リファクタリング対象の関数ブロック全体を選択するか、関数宣言行にカーソルを置きます。明確に対象を囲むことで、隣接する関数やインポート文への予期せぬ改変を防ぎます。

ステップ 2: Code Lens から Auto Edit を起動する

関数ヘッダーの上に表示されている Auto Edit Code Lens をクリックします。選択範囲がコンテキストとして固定され、指示入力バーがアクティブになります。

ステップ 3: 具体的かつ構造的なプロンプトを入力する

「この関数を改善して」のような曖昧な指示は避け、設計意図、構造上の制約、互換性の維持を明確に記述します。

ステップ 4: エディタ内で差分(Diff)を検証する

Mutable.ai が変換コードを生成すると、エディタ内でビジュアル差分が表示されます。

呼び出し元の互換性が維持されているか、例外の送出パターンが変わっていないかを厳密に確認します。

ステップ 5: 反映、追加指示、または破棄


4. 実践例:レガシーな注文処理関数のリファクタリング

以下は、コールバックのネストと暗黙の処理、古いキャンペーンの残骸が混在したレガシーな JavaScript コードの例です。

リファクタリング前(Before)

function processOrder(order, callback) {
    if (order) {
        if (order.id && order.items && order.items.length > 0) {
            var total = 0;
            for (var i = 0; i < order.items.length; i++) {
                if (order.items[i].price && order.items[i].qty) {
                    total += order.items[i].price * order.items[i].qty;
                } else {
                    // 2021年の特別キャンペーン用フォールバック(現在は廃止)
                    if (order.legacyPromo) {
                        total += 10;
                    }
                }
            }
            if (order.user && order.user.email) {
                database.saveOrder(order.id, total, function(err, res) {
                    if (err) {
                        callback(err, null);
                    } else {
                        emailService.sendReceipt(order.user.email, res, function(err2) {
                            if (err2) {
                                callback(null, { status: "partial_success", res: res });
                            } else {
                                callback(null, { status: "success", res: res });
                            }
                        });
                    }
                });
            } else {
                callback(new Error("Missing user email"), null);
            }
        } else {
            callback(new Error("Invalid items payload"), null);
        }
    } else {
        callback(new Error("Empty order"), null);
    }
}

Auto Edit への自然言語指示

「processOrder をモダンな TypeScript にリファクタリングしてください。コールバックを async/await に変更し、多重ネストを早期リターンのガード節で平坦化し、合計金額の計算を個別のヘルパー関数に抽出し、legacyPromo の廃止ロジックを削除して、Order と OrderResult のインターフェース型を定義してください。」

リファクタリング後(After)

interface OrderItem {
    id: string;
    price: number;
    qty: number;
}

interface Order {
    id: string;
    items: OrderItem[];
    user: { email: string };
}

interface OrderResult {
    status: "success" | "partial_success";
    res: unknown;
}

function calculateOrderTotal(items: OrderItem[]): number {
    return items.reduce((sum, item) => sum + item.price * item.qty, 0);
}

async function processOrder(order: Order): Promise<OrderResult> {
    if (!order) {
        throw new Error("Empty order");
    }
    if (!order.id || !order.items || order.items.length === 0) {
        throw new Error("Invalid items payload");
    }
    if (!order.user?.email) {
        throw new Error("Missing user email");
    }

    const total = calculateOrderTotal(order.items);
    const res = await database.saveOrder(order.id, total);

    try {
        await emailService.sendReceipt(order.user.email, res);
        return { status: "success", res };
    } catch (emailError) {
        return { status: "partial_success", res };
    }
}

リファクタリングによる改善点:

  1. 循環的複雑度の半減: 6段階あったインデントのネストが、平坦なガード節により1段階に縮小。
  2. ゾンビコードの根絶: 動作保証のない古い legacyPromo 分岐を安全に除去。
  3. 責務の分離: 金額計算を calculateOrderTotal に切り出すことで、個別単体テストが容易化。
  4. コンパイル時の型安全性: TypeScript の型定義により、呼び出し元での入力ミスを防止。

5. ベストプラクティスと注意点

自然言語リファクタリングをチーム開発で成功させるための指針です。

推奨プラクティス

避けるべきアンチパターン


6. プロダクトの現状と現代の開発ツール生態系

Mutable.ai は 2021 年に Omar Shams と Maxwell Siegelman によって設立され(Y Combinator W22)、コードベース自動ドキュメント生成(Auto Wiki)やリポジトリ認識型コーディング支援の先駆者として注目を集めました。

2024年12月、Mutable.ai は Alphabet(Google)によって買収されました。この買収に伴い、単独製品としての Mutable.ai サービスおよび VS Code マーケットプレイス上の拡張機能は役目を終え、Google の社内技術基盤へと統合・移行されました。現在スタンドアロン版の新規導入は行われていませんが、Mutable.ai が切り拓いた「エディタ内でのその場自然言語指示」「コードベース全体の文脈把握」「ネイティブな差分確認」という設計思想は、現代の Cursor(Composer)、GitHub Copilot Edits、Continue.dev、Aider などに広く受け継がれ、業界の標準的なリファクタリング手法として定着しています。


参考文献