コードの複雑性を定量評価する尺度(メトリクス)には経路の総数、ネストの深さ、循環的複雑度(サイクロマティック複雑度)があります。しかし、経路の総数とネストの深さはフローの構造に依存するブレが大きく、循環的複雑度はそのブレが小さいことが、いくつかのコードを見ていて思いました。ここでは、その具体例と、それらのメトリクスの特徴について考察しました。
循環的複雑度については前回の循環的複雑度でフローの複雑性を把握するで解説しています。循環的複雑度は、簡単にいうと、エッジとノードで囲まれた領域の数です.
具体例
テストの点数を与えると、その評価を返すメソッドevaluationXを考えます。評価は次の通りです。
簡単のため、与える点数は必ず0以上100以下と仮定します。
上記の機能を実装したメソッドを3つ考えます。
例1 『深くネスト』
private String evaluation1(int score) { String eval = "優"; if (score < 100) { eval = "良"; if (score < 80) { eval = "可"; if (score < 60) { eval = "不可"; } } } return eval; }
例2 『分岐とネスト』
private String evaluation2(int score) { String eval = "優"; if (score < 100) { eval = "良"; } if (score < 80) { eval = "可"; if (score < 60) { eval = "不可"; } } return eval; }
例3 『分岐+分岐+分岐』
private String evaluation3(int score) { String eval = "優"; if (score < 100) { eval = "良"; } if (score < 80) { eval = "可"; } if (score < 60) { eval = "不可"; } return eval; }
経路の総数、ネストの深さ、循環的複雑度の特徴
上記例において、経路の総数、ネストの深さ、循環的複雑度はそれぞれ次のようになります。
例 | 経路の総数 | ネストの深さ | 循環的複雑度 |
---|---|---|---|
経路の総数とネストの深さは値のブレが大きく、フロー構造に大きく依存していることが分かると思います。しかし,循環的複雑度は一定値であり、フロー構造に依存していないように見えます。
複雑度を定量化するとき、直感的に思い浮かぶのは経路の総数でした。経路が多ければ複雑というのはなかなか的を得ているように思いましたが、人が見れば経路が多くてもフローが分かりやすく複雑とは感じないコードもあります。おそらく、人が複雑と感じるのはフローの構造が入り組んでいる状態だと思います。循環的複雑度は、フローの分岐、合流という構造に単位性を持たせて評価する尺度ですので、人が感じる複雑性をより具体化しているように思いました。