# Perl コードのメトリクス測定 ## コードを静的解析する {{TOC 3-}} ### メトリクス解析ツール Perl コードのメトリクス解析には {{cpan: Perl::Metrics::Lite}} やコマンドラインツールの {{cpan: App::plmetrics}} を使用します。 #### plmetrics {{cpan: App::plmetrics}} モジュールにはコマンドラインでメトリクス解析を簡単に行う {{cpan: 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= | --file= | --dir= | --git= | --tar=] [--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 {{cpan: 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 という感じで、閾値を超えたファイルがレポートされます。 Jenkins さんに食わせるのに便利ですね! #### Test::Perl::Metrics::Lite {{cpan: 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 が開発したもので、プログラムの複雑度を測るのに使われる。プログラムのソースコードから、線形的に独立した経路の数を直接数える。 << http://ja.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E7%9A%84%E8%A4%87%E9%9B%91%E5%BA%A6 循環的複雑度 - wikipedia 個人的にいろいろ計測してみたのと、読みやすさ、やり過ぎない程度を勘案して、以下のような基準で運用してみると良いのではないでしょうか。 ----------------------|--| 10 | シンプルでテスタビリティも高いはず。しかし、意図的に関数を分割しすぎて全体の処理が見えにくくならないように注意が必要 | 11 - 15 | 通常はこの範囲に収まる。また、テストカバレッジを高く維持するにはこの程度でないと厳しい | 16 - 20 | ぱっと読んでちゃんと動くかな?というレベル。一部テストがまともに書けない状態になってくる | 21 - 25 | さらりとは読めない。できれば分割したいところ。おそらく細かいテストはもはや書けない | 26 - | 黒歴史化確定。といいつつも、処理内容によってはこの程度のものはありえます | たまに計測をして、リファクタリング対象をあぶりだすか、Test に組み込んで必ずクリアするようにするかは、ものによるかと思います。 ビジネスにおけるプロダクト(特に一般ユーザ向けのウェブアプリケーション)では、リリースのスピードをもとめられると思うので、その点も考慮しなければならないでしょう。 ただし、複雑度の高さが、やがてプロダクトの改修の足を引っ張るということは常に意識しておかないとただ計測するだけに終わってしまいます。 静的解析が、快適で楽しいコーディングの一助になれるといいですね!