理系学生日記

おまえはいつまで学生気分なのか

Vibe Codingでどんどんコードが発散していくのを、AIとlizardとsimilarity-pyで防ぐ

小さなツールであれば、もうClaude Codeでいいよね、自分で書く必要ないよね、という気になってきた。 TeamsのWEBVTTから議事録を作るツール、僕は1行も書いてない(実際のところは、devcontainer設定ファイルだけいじった)。

でも、機能追加とか仕様変更とかそういうのの実装をAIに依頼し続けると、どうしてもコードが肥大化していく。 肥大化は肥大化でも、やたらメソッドが長くなっていたりとか、同じようなコードが何度も出てきたりとか、そういう感じになる。これは人がやってもそうで、その不可避性はエントロピー増大の法則が証明している。しかし、生産性の高いAIに任せるとエントロピーの時間発展が尚更早くて、あっという間にコードが発散していく。

エントロピーの時間発展に対しては、それを防ぐだけの力が必要になる。

テストカバレッジを増やす

まずはテストカバレッジを増やす。

雑然としたコードが増えていくのは必然だけど、それを再整理するのはリファクタリングであり、リファクタリングにはコードの挙動を変えないという前提が必要になる。コードの挙動を変えていないというガードレールはテストであり、それを証明するテストコードを生成AIに与えれば良い。

人がテストカバレッジを増やすのは大変だったけど、生成AIはテストコードを生成するのが得意なので、テストカバレッジを増やすのは難しくない(レビューするのは辛いが)。僕は、ファイルごとに85%以上のカバレッジを目指せとCLAUDE.mdで指示している。

サイクロマティック複雑度を減らす

テストというガードレールを引いたら、次は複雑性に向き合う。

雑然としたコードを定量的に表現する指標の1つはサイクロマティック複雑度(CCN)だ。サイクロマティック複雑度を図るツールはいくつかあるけど、CLIで簡単に使えるので、僕はLizardを使っている。

CCNが10を超えるようなメソッドはリファクタしろ、というのを指示するようにしてる。CCNの値としてどのくらいが良いのかというのはあまり定まっていないようだけど、生成AIに聞いたら5〜10くらいが良いのではないかと言っていた。

類似度を減らす

CCNが高いメソッドをリファクタしようとすると、多くの場合メソッドを責務によって分解することになる。結果としてメソッドの数が増える。それがあちらこちらで行われると、今度は分解されたメソッドの責務が似通うことになり、同種のメソッドが増えていく。 これを防ごうとすると類似度が必要となり、僕はsimilarity-pyを使っている。

similarity-pyで0.8以上の類似度の場合はリファクタしてもらうようにしている。ただ、それだけだと激しいリファクタになってしまう感じだったので、メソッド行数8行以上という条件もつけるようにした。

similarity-py src/vtt2minutes/ --threshold 0.8 --min-lines 8
Analyzing Python code similarity...

=== Function Similarity ===
Checking 7 files for duplicates...

Duplicates in src/vtt2minutes/bedrock.py:
------------------------------------------------------------
  src/vtt2minutes/bedrock.py:261-300 method _validate_bedrock_access <-> src/vtt2minutes/bedrock.py:517-552 method get_available_models
  Similarity: 80.61%
  Classes: BedrockMeetingMinutesGenerator <-> BedrockMeetingMinutesGenerator
  src/vtt2minutes/bedrock.py:374-403 method _create_fallback_prompt <-> src/vtt2minutes/bedrock.py:483-515 method _extract_response_text
  Similarity: 96.75%
(略)

あとは、生成AIがリファクタ要否を判断し、必要に応じてリファクタしてくれる。

AIがない時代と何が変わったのか

例えばCCNを算出するようなプラクティスはこれまでもあった。でも、それが実際に活躍することが少なかったのは、その数値をもとにして「本当にリファクタする必要があるのか」の判断、そしてリファクタ要と判断しても「実際のリファクタ、そしてその後のテスト」が人の手に委ねられ、その作業も含めて大変だったからだと思う。

でも生成AIがあれば、リファクタの判断も実際のリファクタも、そしてテストも、AIに任せることができる。 例えば以下の画像のように、類似度は高くとも、リファクタは不要という判断をしてくれる。この判断の物量をAIに委譲できるようになったことが大きな変化だと思う。

まとめ

生成AIの登場により、コード品質管理のアプローチが変わってきた気がする。これまでは「測定はできるが改善が大変」だった品質指標が、AIによって「測定から改善まで自動化」できるようになった。テストカバレッジ確保→CCNでメソッドの複雑性を削減→類似度で汎化・抽象化という流れをAIに頼ることができる。

これまでは人手による改善コストが高すぎて実用的じゃなかった。でも生成AIなら、判断から実装、テストまでを一貫して任せられる。 結果として、Vibe Codingで発散しがちなコードエントロピーに対して、継続的な秩序維持が可能になった気がする。 エントロピー増大の法則に逆らうには相応のエネルギーが必要だけど、そのエネルギー源として生成AIを活用できるようになったのが、大きな変化だと思う。