プログラミングとデバッグ出力
プログラムを開発する際、デバッグ (不具合修正) は、まずはどこで何が起こっているかを書き出す事が重要です。また、処理状況を書き出しながら開発すると、間違いに早く気付いて開発を効率よく行えます。この目的で Perl には warn や die といった状況書き出し用のコマンドがあります。また、より詳しく状況を出力するために Carp や Data::Dumper という標準モジュールもあります。
これらの標準機能を使う場合は、例えば以下のようにコード内に記載します。
warn "\$valname = $valname\n";
use Data::Dumper; warn "\%hashname = " . Dumper(\%hashname) . "\n";
それぞれ出力は以下のようになります。
$valname = 32
%hashname = $VAR1 = { 'key2' => 'abc', 'key1' => 123 };
デバッグ用の書き出しはプログラミング上必須ですが、開発時に書き出したものを運用時に消すのはなかなか面倒なものです。また、出力コードを書く事自体が面倒でついつい省略して開発を進め、不具合の落とし穴にはまってしまう事もあります。
という事で、この面倒な書き出し (「デバッグ出力」と呼びます) を簡単に行えるモジュール Smart::Comments の使い方を紹介します。
Smart::Comments モジュールの概要
Smart::Comments は CPAN モジュールです。このモジュールを使うと、プログラムコード内で「###」 (シャープ3つ) で始まるコメントをデバッグ出力指令として解釈してくれます。例えば、
### $valnameと記載すると、プログラム実行時に画面以下のように出力されます。
### $valname: 32
デバッグ出力の記載が簡単な上、開発が終わって運用局面に入ればモジュールの使用を止める事で全てのデバッグ出力を抑える事ができますので大変便利です。
Smart::Comments モジュールのインストール方法
Smart::Comments モジュールのインストール方法は他の CPAN モジュールと同じです。
コメントの記載方法
Smart::Comments でメッセージを出力する場合、一定の記載ルールがあります。変数の出力
変数の内容を出力したい場合、「#」3つに続けて変数名を記載します。
### $valname ### %hashname出力は以下の通りです。
### $valname: 32 ### %hashname: { ### key1 => 123, ### key2 => 'abc' ### }
また、変数だけでなく、計算結果なども出力できますが。この場合はコロンで結んで左辺と右辺に同じ表現を記載します。
### $valname * 2 : $valname * 2出力は以下の通りです。
### $valname * 2 : 64
なお、perldoc で表示されるマニュアルには以下の記載でもOKと書かれている場合がありますが、私が確認したバージョンでは機能しませんでした。
### $valname * 2
コメントの出力
たとえば「ファイルの読み込み開始」などの処理状況を出力したい場合は、「#」3つと「.」 (半角ドット) 3つに挟んで出力したい内容を記載します。
### 出力コメントの例...出力は以下のようになります
### 出力コメントの例...コメントには、以下の固定表現でファイル名や行数、時刻、変数を含む事ができます。
### [<now>] 処理開始... ### [<where>] 次の処理に進む... ### [<file>(<line>)] 次の処理に進む... ### [$file] を開きます...これらの出力は以下のようになります。
### [Tue Jul 14 14:24:36 2015] 処理開始... ### ["comment_sample.pl", line 32] 次の処理に進む... ### [comment_sample.pl(34)] 次の処理に進む... ### [filename.txt] を開きます...
ループ処理
for や while のループ処理をする際に、進行状況を表示する事ができます。この機能は、大量の情報をループ処理する時に処理が進んでいるのか、止まってしまっていないかを確認するために役立ちます。
記載方法は下記のように、ループブロックの開始カッコの後に「#」3つに続けて出力したい内容を記載します。「%」をコメント内に含めると、どこまで処理が終わったかをパーセンテージで表示してくれます。
for (@values) { ### 処理中 (% done) # : ここで何かの処理 }
なお、ループ処理のコメントについては日本語 (utf8) 出力でワーニングが出るバージョンがあるようですので、以下のようなエラーが出たら英数字だけのコメントに変更して下さい。
Wide character in print at /usr/lib/perl5/site_perl/5.x.x/Smart/Comments.pm line #.
値のチェック
ところで、サブルーチンを作った時には「単体テスト」というものを行いましたね。この時は Test::More という標準モジュールを使いましたが、Smart::Comments でもこれに似た発想で、コードの中途で値のチェックを行う機能があります。
例えば、ある変数の内容が2以上でなければならない場合、「assert: (条件式)」という表現を使います。
### assert: 2 <= $valnameと記載すれば、$valname が2以上でない場合そこでプログラムの実行が停止します。
この時の出力例は以下の通りです。
### 2 <= $valname was not true at comment_sample.pl line #. ### $valname was: 1プログラムの停止まではせず、確認だけして処理を先に進めたい場合は「assert」の代わりに「check」を使って下さい。
### check: 2 <= $valname
このような値のチェックには Perl の条件式が自由に使えますが、1行に収まる範囲で書かなければならないのであまり複雑なチェックはできません。例えば配列の内容を丸まる比較しようとしてもうまく行かず、
### assert: @array == @anotherこのチェックは、2つの配列の要素数が同じでさえあればエラーを出さずに進みます。要素数が違い条件に合致しない場合は配列の内容まで詳しく表示してくれますが、このチェックはあまり役に立たないですね。詳細なチェックが必要な場合は手動でチェックフローを書いて下さい。
次は:>運用時に必要なコメント残す方法