Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

\バグだー!/ システムに巣食うバグさんからみた快適さ、循環的複雑度( Cyclomatic Complexity ) とは? \バグだー!/

f:id:tbpg:20150515231252j:plain

概要

循環的複雑度( Cyclomatic Complexity )バグの混入率 について

経緯

現在、私の所属する組織ではシステム全体の 保守性に関して課題を抱えています
今後、改善を行う際の 1 つの指標として循環的複雑度を測定しようと考えました。

一つのきっかけとしては、下記の記事です。

tchikuba's blog - ドワンゴ吉村総一郎氏「Play2/Scalaでドメイン駆動設計を利用した大規模Webアプリケーションのスクラム開発の勘所」@デブサミ2014 2日目

ドワンゴニコニコ生放送のシステムが、 PHP300 万行のコードベース で、
循環的複雑度 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

f:id:tbpg:20150515231307p:plain

if 文が 1 つあるケース(循環的複雑度 2)

class Hoge
  def hoge(flg)
    if flg
      "true hoge"
    else
      "false hoge"
    end
  end
end

puts Hoge.new.hoge

f:id:tbpg:20150515231318p:plain

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

f:id:tbpg:20150515231325p:plain

循環的複雑度とバグの混入率

循環的複雑度 複雑さ バグ混入率 さん快適度
10以下 シンプルなプログラム。リスクがほとんどない 25%
40以上 ほどほどの複雑さのコード。ややリスクがある 50%
50以上 かなり複雑なコード。リスクがある 70%
75以上 いかなる変更も誤修正を生む 98%

循環的複雑度を計測するツール群

深く掘り下げませんが、以下のようなツールがあります。

外部資料