概要
循環的複雑度( Cyclomatic Complexity ) と バグの混入率 について
経緯
現在、私の所属する組織ではシステム全体の 保守性に関して課題を抱えています 。
今後、改善を行う際の 1 つの指標として循環的複雑度を測定しようと考えました。
一つのきっかけとしては、下記の記事です。
tchikuba's blog - ドワンゴ吉村総一郎氏「Play2/Scalaでドメイン駆動設計を利用した大規模Webアプリケーションのスクラム開発の勘所」@デブサミ2014 2日目
ドワンゴ の ニコニコ生放送のシステムが、 PHP の 300 万行のコードベース で、
循環的複雑度 600 超 のメソッドが複数ある状態だったそうです。
循環的複雑度 600 超は「 人類の英知を結集しても不具合を入れずに不具合改修することが困難なレベル 」。
バグを 1 件直すと 直した以上のバグがでる 。そんなレベルです。
そのような状況に直面したドワンゴは、システムリプレイスにより 5 万行のコードベース に改善したとのこと。
システム改善の指標として 数値で結果が出ることは分かりやすい ですし、 社内の経営層に報告しやすい です。
また、改善後に 外部にアウトプットする際にも分かりやすく、 インパクト を生みます。
つまり、
- システム改善の成果の目安
- 今後の開発で維持すべき品質の目安
- システム改善の成果を経営層に実績として分かりやすく伝える
- 改善後にブランディングの一環として、外部に成果をアウトプットする際の分かりやすさがアップ
などの効果を期待できます。
循環的複雑度とは?
プログラムの 複雑度を測る ことを目的としたソフトウェア測定法です。
ソースコードの 経路の数 を数えることで複雑度を計測します。
if , for, while などがない場合は経路が 1 つであるため、複雑度は 1 です。
サンプル
Ruby の例
Ruby のメトリクス分析用ライブラリである metric_fu gem の中の 1 ツールである Saikuro を利用して、
複雑度を測定してみます。
分岐がないケース(循環的複雑度 1)
class Hoge def hoge "hoge" end end puts Hoge.new.hoge
if 文が 1 つあるケース(循環的複雑度 2)
class Hoge def hoge(flg) if flg "true hoge" else "false hoge" end end end puts Hoge.new.hoge
if 文がネストして 2 つ, while 文が 1 つあるケース(循環的複雑度 4)
class Hoge def hoge(flg, inner_flg, count) if flg if inner_flg i = 0 while (i < count) do puts "true-true hoge" count -= 1 end else puts "true-false hoge" end else puts "false hoge" end end end Hoge.new.hoge
循環的複雑度とバグの混入率
- Info-Q - Cyclomatic Complexity Revisited のグラフの内容をもとに、表にまとめました。
循環的複雑度 | 複雑さ | バグ混入率 | さん快適度 |
---|---|---|---|
10以下 | シンプルなプログラム。リスクがほとんどない | 25% | |
40以上 | ほどほどの複雑さのコード。ややリスクがある | 50% | |
50以上 | かなり複雑なコード。リスクがある | 70% | |
75以上 | いかなる変更も誤修正を生む | 98% |
循環的複雑度を計測するツール群
深く掘り下げませんが、以下のようなツールがあります。