Cyclomatic complexity - Wikipedia, the free encyclopedia。日本語では、循環的複雑度 - Wikipediaと呼ぶみたい。
Cyclomatic complexity は、(Wikipedia に書いてありますが)コードの中で独立した処理の進み方がいくつあるかを示したもので、コードの複雑度の指標となります。Sublime Text 2 で JSHintの記事でもそういえば書いていましたが(忘れてた)、Cyclomatic complexity は 10 以下が妥当な範囲としています(Testable JavaScript参照)。JSHint ではmaxcomplexityで設定することができます。
計測には、M = E - N + P という計算式が使われます。詳細はCyclomatic complexity - Descriptionに書かれていますが、Javascript の function は、function の処理が終わった後は、処理を実行した場所(entry point)に戻るので、Javascript の function の Cyclomatic complexity を調べるなら、2P ではなく P になる(日本語の Wikipedia はそのあたりの説明が薄い)。
この式の M は complexity で、E が edge の数、N が node の数で、P が exit node の数になる(javascript function の場合、常に 1 つだけになる)。Cyclomatic complexity - Implications for Software Testingの内容を参考にすると、
function () {
if (c1()) {
f1();
} else {
f2();
}
if (c2()) {
f3();
} else {
f4();
}
}
のような処理を control flow graph にすると、添付の図のようになる。edge(E)は矢印の部分になる。node は丸の部分で、赤丸が entry point、青色が exit point となっている。
edget(矢印)と node(丸)をそれぞれ数えると、9 個と 7 個になるので、Complexity の M は、M = 9 - 7 + 1 で、3 となる。
つまり、Cyclomatic complexity は、入り口から出口までにあるコードのブロック(node)に対して、ブロック間を行き来する道がどれだけあるかを表したものであると。ブロックの数と比較して道が多くあるということは、色んな進み方ができるということであり、バグにつながる確率が高くなると。そして Cyclomatic complexity は 10 までに押さえるのがよしと。それ以上になる場合は、処理の方法を変えるとか(if 文ではなく functon map みたいなかたちにするとか)、function を目的別に分割するとかして、コードの簡潔性を保つのが良い。
また、既存の機能に条件分岐を増やして、Cyclomatic complexity が二倍三倍になるような修正は、バグを含みやすいので、あまり良い修正方法とは言いがたいと。
というメモ。