Perl スクリプトに assertion code を埋め込む実験中 ― 2006年12月05日 21時56分09秒
この記事の続きというか後日談というか。現在製作中の若干大きめのプロジェクトにおいて、自作の assertion code がそれなりに役立っているので、一応現状使っているものとほぼ等価のコードを示しておこうと思う。
sub assert (&) { return unless $debug_mode; shift->() and return; # assertion 失敗時の処理 my (undef, $filename, $line) = caller; my $main_file = main::__FILE__; print STDERR <<ENDLINE; $main_file: Assertion faild at $filename line $line ** Call stack ** ENDLINE my $i = 0; while (my ($pkg, $file, $l, $sub, undef, undef, $evaltxt, $is_req) = caller $i++){ $is_req = $is_req ? 'YES' : 'NO'; print <<ENDLINE; -- stack frame #$i: at $file (package $pkg) line $l -- ENDLINE print $file eq '(eval)' ? <<ENDEVALBLOCK : $sub eq '(eval)' ? <<ENDEVALTEXT : <<ENDSUB; type : eval block is require : $is_req ENDEVALBLOCK type : eval text is require : $is_req eval text : $evaltxt ENDEVALTEXT type : subroutine subroutine : $sub ENDSUB } die "\n"; }
使い方としては、例えばこんな感じ。
$debug_mode = 1; # 本来このインターフェースはもうちょっと別の形で用意されるべき # 最大値を求める sub maxNumber { my $max = shift or return; for my $number (@_){ assert { $number eq $number + 0 }; # 数値以外の値は渡されないはず $max = $number if $max < $number; } $max } my $num1 = maxNumber -2, -70, 6, 4.3; print "num1: $num1\n"; my $num2 = maxNumber 37, -256, 1.25e+17, 'infinity'; # assertion faild!! print "num2: $num2\n";
実用的かどうかはまだ検討中。プロジェクトではまだ小さいデータでしか試せてないのよ。もしかしたら実用には耐え難いほどに処理を重くしてしまうかもしれない (しょっちゅう無名関数を生成するし、少なくともデバッグモードか否かの判定は行われるからね)。
ただ、おいらの場合、大き目のプログラムを作る場合において、部品となる部分のプログラムを作って動作を確認しながら、それらを繋ぎ合わせて大きくする、という手順は踏まずに、大まかに設計した枠組みに沿って全体をどかっと書き始め、問題点をフィードバックしつつ実装し、ある程度出来上がったところで試しに走らせてバグ潰しをする、というやり方で作ってしまうことが多いので、assertion code を埋め込む仕組みがあるのと無いのとではバグ潰しのはかどり具合が全然違ってきてしまう。そういう意味では今のところ、かなり重宝していたりします (それだけバグが多いということですが。。。T-T/)。
コメント
トラックバック
このエントリのトラックバックURL: http://harapeko.asablo.jp/blog/2006/12/05/984126/tb
※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。
コメントをどうぞ
※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。
※投稿には管理者が設定した質問に答える必要があります。