どこでも見れるメモ帳

とあるSEの備忘録。何かあれば気軽にコメントください〜

SRP(単一責任原則)とCC(循環的複雑度)によるコンポーネント内の技術的負債の定量化

はじめに

ソースコードを静的解析することでRailsコンポーネント(単一ファイル)の技術的負債を定量化します.
方針はこちらの記事*1に従って行います.
なお,SRPの算出はgit blameを用いて*2行い,CCの算出はrubocopのMetrics/CyclomaticComplexityを用いて行います.

# ref: 第8回 Perlによる大規模システム開発・設計のツボ(3):Perl Hackers Hub|gihyo.jp … 技術評論社
#      http://gihyo.jp/dev/serial/01/perl-hackers-hub/000803

# コンポーネントの単一責務性の違反指数(SRP)
#   SRP=R+U+((L/100)-5)
#     R:修正リビジョンのユニーク数
#     U:修正ユーザのユニーク数
#     L:モジュールのライン数
function get_SRP() {
  local target_filepath=$1
  echo $(( \
    $(git --no-pager blame --line-porcelain $target_filepath | sed -n 's/^summary //p' | sort | uniq -c | sort -rn | wc -l) + \
    $(git --no-pager blame --line-porcelain $target_filepath | sed -n 's/^author //p' | sort | uniq -c | sort -rn | wc -l) + \
    ( $(cat $target_filepath | wc -l) / 100 - 5) \
  ))
}

# コンポーネントの循環的複雑度(CC)
#   CC=循環的複雑度が20を超えるメソッド数
function get_CC() {
  local target_filepath=$1
  echo $( \
    rubocop --format simple --only Metrics/CyclomaticComplexity --config <(echo -e "CyclomaticComplexity:\n  Max: 20") $target_filepath | grep 'Cyclomatic complexity' | wc -l \
  )
}

# コンポーネントの負債指数(P)
#   P=SRP×CC+(SRP+CC)
function get_P() {
  local srp=$1
  local cc=$2
  echo $(( $srp * $cc + ( $srp + $cc ) ))
}

# コンポーネントの負債指数(P)が大きい順に "P SRP CC ファイル名" を標準出力
for file in `git ls-files app lib | grep -E '\.rb$'`; do
  _srp=$(get_SRP $file)
  _cc=$(get_CC $file)
  echo $( get_P $_srp $_cc ) $_srp $_cc $file
done | tee technical_dept_result.log | sort -k1,1 -nr 

※gistはこちら*3

関連する過去記事

ni66ling.hatenadiary.jp ni66ling.hatenadiary.jp

*1:第8回 Perlによる大規模システム開発・設計のツボ(3):Perl Hackers Hub|gihyo.jp … 技術評論社 - http://gihyo.jp/dev/serial/01/perl-hackers-hub/000803

*2:git blameによるSRP(単一責任原則)の定量化 - どこでも見れるメモ帳 - http://ni66ling.hatenadiary.jp/entry/2015/06/25/000444

*3:技術的負債の定量化 - https://gist.github.com/KenshoFujisaki/9cefd372c9cec0814a08