コードの乱雑さを測る:メトリクス、発見、コミュニティの知見

TL;DR

LLMが生成するコードは形式的には正しくても、人間が書いたコードと比べて著しく乱雑であることが判明した。LOCの変化、冗長性、エロージョンといった単純なメトリクスから、エージェントが既存のリポジトリの約2倍の冗長性とエロージョンを生成していることが明らかになった。また、既存の評価手法ではこの劣化を捉えられていない。


乱雑さを測ることが重要な理由

隠れたテストを通過するコードでも、不要な抽象化、重複する論理、劣悪なアーキテクチャ設計を含むことがある。月に数百万行のコードを追加する大規模プロジェクトでは、この「乱雑さ」が開発者の人間的主体性を侵食する。著者は、エージェントが乱雑さを自律的に解決できないため、定量的な評価が不可欠だと主張している。


単純な評価アプローチは失敗する

AIが審判となるのは信頼できない

  • LLMに自身のコードを1〜10のスケールで評価させると、ランダムな数値生成器と同様の振る舞いになる。
  • ペアワイズ比較(「A vs B」)は不安定である:ソリューションの名前を変えるだけでモデルの好みが逆転することがあり、arXiv:2604.16790で示されている。
  • 高度な評価基準やLLMが生成するテストでも、乱雑さを完全に排除することはできない。

"LLMに自身が書いたコードを評価させることは、適切な評価の代わりにはならない。" – 著者

ヒューマンインザループはスケーラブルではない

  • ヒューマンレビューは読みやすさを保証するが、トレーニングやベンチマークスイートに必要な規模には対応できない。
  • 数百万行のLOCをレビューするコストは、モデル提供者の継続的なランク付けの利点を上回る。

単純なメトリクス:LOCの変化

コード修正後のLOCのネット変化を数えることで、乱雑さを効果的に検出できることがわかった。しかし、著者はこのメトリクスを最適化しようとするとグッドハートの法則が発動する可能性に注意を促している——メトリクスが目標になると、そのメトリクスはもはや良い指標ではなくなる。


SlopCodeBench からの研究ベースのメトリクス

論文 SlopCodeBench(arXiv:2603.24755v1)は、レガシーコードベースとLLM生成の乱雑さを分離する2つのメトリクスを導入している。

冗長性(Verbosity)

重複または不要な冗長な行を測定する:

$$ \text{Verbosity} = \frac{|\text{AST‑Grepでマークされた行} \cup \text{クローン行}|}{\text{LOC}} $$

  • AST‑Grepを用いた手動で設計されたヒューリスティクスで実装。

エロージョン(Erosion)

コードの質量が少数の巨大で複雑な関数に集中している程度を測定する:

$$ \text{mass}(f) = \text{CC}(f) \sqrt{\text{SLOC}(f)} $$ $$ \text{Erosion} = \frac{\sum_{f:,\text{CC}(f)>10}\text{mass}(f)}{\sum_{f}\text{mass}(f)} $$

  • CC(f) は循環複雑度、SLOC(f) はソース行数を表す。

実証的発見

データセット 冗長性(平均 ± 標準偏差) エロージョン(平均 ± 標準偏差)
既存の人間によるリポジトリ 0.15 ± 0.06 0.31 ± 0.17
エージェントが生成したコード(SlopCodeBench) 0.33 ± 0.10 0.68 ± 0.20
  • エージェントは人間のコードの約2倍の冗長性とエロージョンを生成している。

著者の自身の「ビーブコード」プロジェクトに対するアンケート的なチェックでは、冗長性が最大0.4、エロージョンが最大0.75に達した。これは、この現象がベンチマークに限定されたものではないことを裏付けている。


エージェントが自己修正できない理由

  • SlopCodeBenchは反復的な設定でエージェントを評価している:各指示-テストラウンドの後、モデルのコンテキストが消去される。これは、コードが多数のステップを経て進化する現実世界の使用状況を模倣している。
  • 悪い決定が蓄積され、最先端モデルでも厳密な解決率が0 % に達する——つまり、どのモデルもすべてのチェックポイントで隠れたテストをすべて通過できない。
  • これは、AIにのみ依存してLOCが無制限に増加することに対する強い警告である。

コミュニティの反応と拡張

"乱雑さの最も重要な問題は局所的なものではなく、グローバルな性質である。関心の分離といったアーキテクチャ的指標が必要だ。" – dherman

"最小LOCを目指すと、実際にはコードゴルフが進み、保守が困難な1行コードが生まれる可能性がある。" – cjalmeida

"循環複雑度、変更頻度、著者情報といったメトリクスはすでに内部ダッシュボードで有用である。これらを組み合わせれば、乱雑さのより豊かな画像が得られる。" – pbjerkeseth

"グッドハートの法則が議論なしに引用されている。LOCを最小化することが本当に乱雑さを増すのか、検証する必要がある。" – drsopp

"現在の議論には、グローバルなアーキテクチャ的メトリクス(例:結合度、一貫性)が欠けており、大規模コードベースでは必須かもしれない。" – dherman

"エージェントがいても、人間による設計作業は依然として必要である。そうでなければ、コードベースは一時的な機能のスパゲッティ状態になる。" – cheney_2004

これらのコメントは以下の3つのテーマを繰り返し強調している:

  1. グローバルなアーキテクチャ的メトリクスの必要性(結合度、一貫性、レイヤリング)。
  2. メトリクスの悪用リスク(グッドハートの法則)と、マルチメトリクススイートの重要性。
  3. 人間の監視が依然として不可欠であり、特に設計と保守性の観点から。

未解決の方向性

著者は今後の研究に有望な道を以下に列挙している:

  • 関数間の結合度 – 関数同士がどれほど密に依存しているかを測定。
  • コードの変更頻度(Churn) – 急速な追加・削除を不安定さの代理指標として追跡。
  • 一貫性(Cohesion) – モジュールの責任がどれほど集中しているかを評価。
  • フィードバックループ – 冗長性/エロージョンスコアをLLMの学習にフィードバックして、よりクリーンなコード生成を促す(グッドハート効果の監視を含む)。

実践者への具体的な教訓

  1. LOCの変化を素早い検証手段として追跡するが、ハードな目標ではなくヒューリスティクスとして扱う
  2. AST‑Grepや同様の静的解析パイプラインを使って冗長性とエロージョンを実装し、重複・過度に複雑なコードを検出する
  3. 複数のメトリクス(複雑度、変更頻度、結合度)を組み合わせて、単一メトリクスの悪用リスクを軽減する
  4. アーキテクチャ的決定には人間のレビューを維持する。自動メトリクスは問題を浮き彫りにできるが、設計判断を代替することはできない
  5. SlopCodeBenchが行っているように、反復的な開発を模倣したベンチマークを設計する。これにより、多数の修正ステップを経て初めて現れる乱雑さを浮き彫りにできる。

結論

LOCの変化、冗長性、エロージョンといった定量的メトリクスは、コードの乱雑さを具体的に捉えるための有効なレンズを提供しており、現在のLLMエージェントが人間が書いたコードの約2倍の冗長性とエロージョンを生成していることが明らかになった。これらのメトリクスは価値があるが、グッドハートの法則を回避し、保守可能なソフトウェアを確保するためには、グローバルなアーキテクチャ的性質と人間の監視を含む、より広範かつ多次元的な評価戦略の一部でなければならない。

Sources

関連