Perl コードのメトリクス測定
コードを静的解析する
メトリクス解析ツール
Perl コードのメトリクス解析には Perl::Metrics::Lite やコマンドラインツールの App::plmetrics を使用します。
plmetrics
App::plmetrics モジュールにはコマンドラインでメトリクス解析を簡単に行う plmetrics が含まれています。
$ plmetrics --module Encode
/usr/lib/perl5/5.8.8/i386-linux-thread-multi/Encode.pm
.---------------------------------------------------.
| | avg | max | min | range | sum | methods |
+-------+-------+-----+-----+-------+-----+---------+
| cc | 7.69 | 18 | 1 | 17 | 100 | 13 |
| lines | 17.92 | 94 | 4 | 90 | 233 | 13 |
'-------+-------+-----+-----+-------+-----+---------'
リモートの git リポジトリを対象に解析することも可能です。
$ plmetrics --git git@github.com:bayashi/Statistics-Swoop.git
lib/Statistics/Swoop.pm
.--------------------------------------------------.
| | avg | max | min | range | sum | methods |
+-------+------+-----+-----+-------+-----+---------+
| cc | 3.00 | 10 | 1 | 9 | 18 | 6 |
| lines | 8.67 | 28 | 1 | 27 | 52 | 6 |
'-------+------+-----+-----+-------+-----+---------'
metacpan の tar.gz もいけます。
$ plmetrics --tar http://cpan.metacpan.org/authors/id/B/BA/BAYASHI/Statistics-Swoop-0.02.tar.gz
lib/Statistics/Swoop.pm
.--------------------------------------------------.
| | avg | max | min | range | sum | methods |
+-------+------+-----+-----+-------+-----+---------+
| cc | 3.00 | 10 | 1 | 9 | 18 | 6 |
| lines | 8.67 | 28 | 1 | 27 | 52 | 6 |
'-------+------+-----+-----+-------+-----+---------'
集計は --result
オプションで指定します。
$ plmetrics --tar http://cpan.metacpan.org/authors/id/B/BA/BAYASHI/Statistics-Swoop-0.02.tar.gz --result method
lib/Statistics/Swoop.pm
.----------------------.
| | cc | lines |
+---------+----+-------+
| minimum | 1 | 1 |
| _calc | 10 | 28 |
| maximum | 1 | 1 |
| average | 1 | 1 |
| new | 4 | 10 |
| result | 1 | 11 |
'---------+----+-------'
詳細は --help
で。
plmetrics [--module=<module> | --file=<file> | --dir=<dir> | --git=<git_repos> | --tar=<tar_url>] [--result=<result>] [--sort]
OPTIONS:
--module local module name
--file local file path
--dir local directory path
--git git repository
--tar URL of tar.gz
--sort sort result table
--result kind of result(module*|methods|cc|lines|files) *default
measureperl-checkstyle
Perl::Metrics::Lite に同梱されている measureperl-checkstyle
は、オプションで計測値の閾値を渡して解析結果を XML で受け取ることができます
$ measureperl-checkstyle --max_sub_lines 60 --max_sub_mccabe_complexity 10 --directory /home/bayashi/dev/_modules/WWW-Pastela/lib
<checkstyle version="5.1">
<file name="/home/bayashi/dev/_modules/WWW-Pastela/lib/WWW/Pastela/App.pm">
</file>
<file name="/home/bayashi/dev/_modules/WWW-Pastela/lib/WWW/Pastela.pm">
<error line="23" column="1" severity="error" message="'paste' method cyclomatic complexity is 25" source="com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheck"/>
</file>
</checkstyle>
という感じで、閾値を超えたファイルがレポートされます。
Jenkins さんに食わせるのに便利ですね!
Test::Perl::Metrics::Lite
Test::Perl::Metrics::Lite を使用して、メトリクス測定結果を testing することができます。いわゆる xt などに入れて活用すると良いと思います。
perl_metrics.t
use Test::Perl::Metrics::Lite (-mccabe_complexity => 10, -loc => 100);
all_metrics_ok();
という感じです。簡単ですね!
ディレクトリ単位やファイル単位で計測から除外することもできます。
use Test::Perl::Metrics::Lite (
-mccabe_complexity => 10,
-loc => 100,
-except_dir => [
'some/dir/path',
'some/dir/foo/path',
],
-except_file => [
'lib/Hoge/Foo.pm',
'lib/Hoge/Bar.pm',
],
);
all_metrics_ok();
どうしても無視リストに加えて切り抜ける場合は、理由をコメントで添えると吉。
数値の意味
解析表示される数値の意味は、以下のようになっています。
File Metrics
項目名 | 意味 |
---|---|
loc | サブルーチンの行数 |
subs | 関数の数 |
packages | パッケージの数 |
Subroutine Metrics
項目名 | 意味 |
---|---|
loc | 行数 |
line_number | ファイルでの行番号 |
mccabe_complexity | 関数の複雑度 |
重要なのは loc と mccabe_complexity です。
loc は単純に関数の行数です。50~60行程度におさえるのを目安として、最大でも100行は超えないようにした方が良いでしょう。
mccabe_complexity は関数の__循環的複雑度__のこと。
循環的複雑度(英: Cyclomatic complexity)とは、ソフトウェア測定法の一種である。Thomas McCabe が開発したもので、プログラムの複雑度を測るのに使われる。プログラムのソースコードから、線形的に独立した経路の数を直接数える。
quoted from: 循環的複雑度 - wikipedia
個人的にいろいろ計測してみたのと、読みやすさ、やり過ぎない程度を勘案して、以下のような基準で運用してみると良いのではないでしょうか。
10 | シンプルでテスタビリティも高いはず。しかし、意図的に関数を分割しすぎて全体の処理が見えにくくならないように注意が必要 |
11 - 15 | 通常はこの範囲に収まる。また、テストカバレッジを高く維持するにはこの程度でないと厳しい |
16 - 20 | ぱっと読んでちゃんと動くかな?というレベル。一部テストがまともに書けない状態になってくる |
21 - 25 | さらりとは読めない。できれば分割したいところ。おそらく細かいテストはもはや書けない |
26 - | 黒歴史化確定。といいつつも、処理内容によってはこの程度のものはありえます |
たまに計測をして、リファクタリング対象をあぶりだすか、Test に組み込んで必ずクリアするようにするかは、ものによるかと思います。 ビジネスにおけるプロダクト(特に一般ユーザ向けのウェブアプリケーション)では、リリースのスピードをもとめられると思うので、その点も考慮しなければならないでしょう。 ただし、複雑度の高さが、やがてプロダクトの改修の足を引っ張るということは常に意識しておかないとただ計測するだけに終わってしまいます。
静的解析が、快適で楽しいコーディングの一助になれるといいですね!