C#でコードの複雑さを測る:循環的複雑度(Cyclomatic Complexity)を攻略しよう
Cyclomatic Complexity in C#
Cyclomatic Complexity in C#
循環的複雑度(Cyclomatic Complexity)は、コードのテストのしやすさや保守性を判断するための強力な指標です。この数値が高いほど、分岐が多くテストケースも増えるため、コードの複雑さが浮き彫りになります。C#開発において、コードの品質を担保し「負債」を減らすために、この複雑度をどのように測定し、制御していくべきかについて解説します。
エージェントのリファクタリングをガイドするために、ndependみたいなツールを使ってる人いる?個人的にはC#やPythonで依存関係グラフを構築してローカルDBに保存するツールを使ってるんだけど、エージェントがそこからリファクタリングのアイデアを見つけるのがかなり上手いんだよね。グラフ解析ツールは役立つよ。単純な使い方だと循環依存の検出くらいだけど、クラスタリングみたいな少し複雑なツールをエージェントに使わせるとデータから面白い発見がある。
セキュリティの観点から見るとCC(循環複雑度)はかなり重要だよ。Pythonコードのセキュリティ面での堅牢性を評価するのに使ってる。信頼性のある[1]を活用してるよ。
[1] https://nocomplexity.com/documents/codeaudit/complexitycheck... (https://nocomplexity.com/documents/codeaudit/complexitycheck.html#complexity-check)
循環複雑度は全体としては便利な指標だけど、現代的な言語で使う場合には一つ欠点があるんだ。それはポリモーフィズムが普及する前に考案されたものだってこと。
つまり「明示的な」分岐しかカウントしないんだよ。例えばC#みたいなオブジェクト指向言語だと、仮想メソッドを呼び出しても循環複雑度は増えない。でも実際には、そのメソッド呼び出しによって多くのコードパスへ分岐し得るわけ。IEnumerableみたいな一般的なインターフェースを扱ってたら、何千ものパスになることだってあるし、ライブラリを作っているならパスの数は無限と言える。
余談だけど、if文やswitch文すらないSmalltalkのような言語でどう適用されるのか考えるのは面白いよね。
オブジェクト指向だけが厄介なわけじゃない。高階関数も循環複雑度では測れない形の分岐を生むしね。
だからって指標として無価値なわけじゃないよ。ただ、コードベースの循環複雑度に制限をかければ保守性が万能になるなんて思わないほうがいい。今まで解読した中で最も理解しがたい関数のいくつかは、実は循環複雑度がかなり低かったりしたからね。
面白い話をしようか。以前のひどい会社で、CC(循環複雑度)が重要視され始めたのと同時期に、PMやマネージャーが当時まだかなりひどかったAIツールを使ってコード変更を強行するようになったんだ(1〜2年前のこと)。結果、レビュー不可能なdiffが山のように押し寄せてきて地獄だったよ。