catch-img

既存コードを安全に直すためのLLM解析のコツ

はじめに

こんにちは、DIVX エンジニアの渡邊です。

今回は、引き継ぎや長期運用など、「コメントや仕様書が薄い・古い・散在している」既存コードを前提に、Claudeを用いて安全に直す際の解析フェーズでのコツを扱います。

既存の保守で生成AIを小さく併用してリスクを抑えたい方向けに、ClaudeなどのLLMでコードを読む際に効いた工夫をまとめました。

背景

既存サービスの保守に、LLMを導入してバグの修正を行おうとしたところ、古いコメントに引っ張られ、頼んでいない箇所の正しい実装を「コメント準拠」に書き換えるような提案をされることがありました。

実例はお示しできませんが、参考となる類似パターンを簡潔に紹介します。秒とミリ秒を取り違えたケースです


初期状態(実装は秒、docstringはミリ秒と記載)

def fetch(url: str, timeout_s: float = 0.5):

    """Timeout in milliseconds."""

    return http_get(url, timeout=timeout_s)

ライブラリは秒指定で受け取る一方、docstringにはミリ秒と書かれています(ここが矛盾)。このような矛盾があると、LLMは次のような修正を提案しやすくなります。


誤った修正(docstringに合わせて実装をミリ秒化してしまう)

def fetch(url: str, timeout_s: float = 0.5):

    """Timeout in milliseconds."""

    return http_get(url, timeout=timeout_s / 1000.0)

docstringを仕様と認識し、引数をミリ秒として扱うように実装を変更(http_getへ渡す前に秒へ変換)してしまっています。

こういった際に効くコツを紹介していきます。

結論

  • 仕様の優先順位を決め、優先順位を明示した上で、ドキュメント化して読ませる

  • 例: 別紙ドキュメント > 実行時挙動/既存テスト > コードコメント >  命名 など

上記が最も正確でしたが、そこまで工数を割くことなく実行可能なのは以下になります

  • 解析プロンプトに「根拠の引用」を入れる

  • 近くに“実行可能な仕様”を置く(doctest・サンプルI/O・型などを関数直上に)

具体例

根拠の引用を必須にする
プロンプトに「根拠の引用」「両案提示」「diff必須」を明示します。

次を守って修正案を出してください:

1) 仕様の根拠として該当箇所を最大3点まで引用({file}:{line}-{line} + 原文)

2) 矛盾があれば「実装修正案」と「コメント更新案」を両方提示

3) 変更は必ず unified diff 形式

4) 公開API・外部I/F・入出力フォーマットは変更しない(必要な場合は別案として提案だけ)

5) 不明点は推測せず「不明」と明記し、追加で必要な情報を列挙

6) 影響範囲(関係する関数/呼び出し元)と最小テストケースを併記

近接に“実行可能なヒント”を置く

関数直上に短いExamples/doctestや型注釈を置きます

def fetch(url: str, timeout_s: Seconds = Seconds(0.5)):

    """

    Timeout in seconds.

    Examples:

        >>> # 0.75秒をそのまま透過して http_get に渡す

        >>> called = {}

        >>> def http_get(url, timeout):

        ...     called['timeout'] = timeout

        ...     return "ok"

        ...

        >>> fetch("https://example.com", Seconds(0.75))

        'ok'

        >>> called['timeout']

        0.75

    """

    return http_get(url, timeout=timeout_s)

モデルは近接する機械可読な手掛かり(型、doctest、サンプルI/O)を強く参照するため、仕様解釈がぶれにくくなります。

効果

主観ベースにはなりますが、以下のような効果がありました

  • 根拠の明示により、推測ベースの修正混入が減った

  • 議論が「どの根拠に沿うか」に収束し、レビューの合意形成が速くなった

  • 関数近傍のdoctest/型情報が誤読のブレーキとして機能し、単位・境界条件の取り違えが減った


さいごに

「解析のしかた」を少し整えるだけで、LLMの提案は扱いやすくなります。

大掛かりな整備が難しい現場こそ、プロンプトと近接のヒントで小さく効かせる。そんなやり方で、LLMの提案はもっと味方になります。




お悩みご相談ください