hns - 日記自動生成システム - Version 2.19.7

void GraphicWizardsLair( void ); //

otsune GWL
FreeBSD, AfterEffects, RETAS, animo, DigitalAnime, Linux, Mac OS, Win2k

[Who is otsune?] [title] [message] [Policy] [注目エントリー] [top]
Twitter Status :


Namazu for hns による簡易全文検索
詳しくは 詳細指定/ヘルプを参照して下さい

検索式:

先月 2006年10月 来月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31


2006年10月13日(金) [長年日記]

#1 [Perl][book] 「Perlベストプラクティス」一通り読んだのでまとめ(後編)

(あくまでも個人的な復習メモ。無保証。1章から7章までは 前日の日記_ に。誤解している可能性はあるので指摘は大歓迎)
Perlベストプラクティス/Damian Conway_

1 8章 組み込み関数:

組み込み関数を使いましょう。自分で作成したコードよりも高速できちんとデバックされている可能性が高い。

1 8.1 ソート:

ソート中にキーを再計算しない。(SHA-512等)
Perl5.8以降のsortのアルゴリズムはマージソート。計算オーダーはO(N log N)。
Orcishマニューバー。計算した結果がハッシュに有ればそれを使い、無ければ||=のor代入で計算してハッシュに入れる。
my %sha512_of;

@sorted_scripts
    = sort { ($sha512_of{$a} ||= sha512($a))
                cmp
             ($sha512_of{$b} ||= sha512($b))
      }
      @scripts;
Schwartzian変換。(シュワルツ変換)
@sorted_scripts
    = map  { $_->[0] }
      sort { $a->[1] cmp $b->[1] }
      map  { [$_, sha512($_)] }
          @scripts;
cmpと<=>の違い。Plagger/lib/Plagger/Feed.pm sort_entriesの例。一部整形。($self->entries->dateの数値でソートして、entriesを入れ替えている。降順)
    my @entries = map { $_->[1] }
        sort { $b->[0] <=> $a->[0] }
        map { [ $_->date, $_ ] } $self->entries;

    $self->{entries} = \@entries;
use Memoizeを使ってサブルーチンの返り値を覚えておく
use Digest::SHA qw( sha512 );
use Memoize;
memoize('sha512');

@sorted_scripts = sort { sha512($a) cmp sha512($b) } @scripts;
どれも一長一短なので、実際のリストでベンチマークを取って決める。

1 8.2 リストの反転:

reverseを使ってリストを反転する。降順sortが欲しい時は昇順sortをreverseする。
reverse sortは最適化されている。

1 8.3 スカラーの反転:

reverseを使ってスカラーを反転する。スカラーコンテキストを明確にするためscalar指定子を付ける。
add_email_addr(scalar reverse $email_address);

1 8.4 固定幅のデータ:

固定幅のデータを抜き出すにはunpackを使う。substrや正規表現はunpackより重い。
'A6 A10 A8'で6文字、10文字、8文字を取得する。
'@0 A6 @8 A10 @20 A8'で列0から6文字、列8から10文字、列20から8文字。
@の値は昇順じゃなくてもいい。

1 8.5 分離されたデータ:

可変幅のデータを抜き出すにはsplitを使う。
第1引数はセパレータ指定。第2引数は文字列。第3引数はフィールドの最大値。
第3引数は必要なフィールド数+1。できるだけ明示的に指定した方が良い。

1 8.6 可変幅のデータ:

可変幅の複雑なデータはText::CSV_XSを使う。
use Text::CSV::Simple;

1 8.7 文字列の評価:

文字列形式のevalは使わない。
eval qq{ sub $subname {...} };で変数名サブルーチンを作るぐらいなら、匿名サブルーチンとSub::Installerを使う。

1 8.8 ソートの自動化:

Sort::Makerでソートルーチン構築を検討する。

1 8.9 部分文字列:

lvalueのsubstrではなく引数4つのsubstrを使う。
substr($addr, $country_pos, $COUNTRY_LEN)
    = $country_name($country_code); # 重い!
ではなく
substr $addr, $country_pos, $COUNTRY_LEN, $country_name($country_code); # ok
にする。代入よりも引数4つのsubstrのほうが高速。

1 8.10 ハッシュ値:

lvalue方式のvaluesを利用する。
forループでvaluesを使うとエイリアスのリストが返るので、ループ中で代入できる(lvalueにできる)

1 8.11 グロブ:

<...>ではなくglobを使う。
入力演算だけで<>を使う。
my @files = glob($FILE_PATTERN);

1 8.12 スリープ:

sleepは整数しか有効ではない。秒単位。Time::HiResを使う。
select undef, undef, undef, 0.5;のhackは使わない。

1 8.13 mapとgrep:

mapとgrepの第1引数に式を使わない。いつもブロックをつかう。

1 8.14 ユーティリティ:

標準ライブラリの関数を使う。
Scalar::Util, List::Util, List::MoreUtilsの関数を使う。
Scalar::Util
  • blessed $scalar
  • refaddr $scalar
  • reftype $scalar
  • readonly $scalar
  • tainted $scalar
  • openhandle $scalar
  • weaken $scalar
  • is_weak $scalar
  • looks_like_number $scalar
List::Util
  • first {<条件>} @list
  • max @list
  • maxstr @list
  • min @list
  • minstr @list
  • shuffle @list
  • sum @list
  • reduce {<$a $bの2項演算>} @list
List::MoreUtils
  • all {<条件>} @list (any(), notall(), none()もある)
  • first_index {<条件>} @list (last_index()もある)
  • apply {<変換>} @list (リストのコピーに変換をかけて新しいリストを返す)
  • pairwise {<$a $bの2項演算>} @array1, @array2
  • zip @array1, @array2, ...
  • uniq @list

1 9.1 呼び出し構文:

サブルーチン呼び出しではカッコを使う。先頭に&を付けない。
(サブルーチンの参照は\&subnameを使う)

1 9.2 同音異義語:

組込関数と同じ名前のサブルーチンはダメ。

1 9.3 引数リスト:

必ず最初に@_を展開する。サブルーチンは引数を@_配列で受け取る。
$_[0], $_[1]は使わない。
sub hoge {
    my ($self, $context, $args) = @_;
    #略
}
例外は、@_を1回だけすぐに処理するラッパーサブルーチン。
sub say {
    return print @_, "\n";
}
#
say( 'Hello' );

1 9.4 名前付きの引数:

サブルーチン引数が3つ以上のときは名前付き引数のハッシュを使う。

1 9.5 欠けている引数:

引数があるかどうかチェックするときは、definedか!undef
引数をif !$argsで検証しない。

1 9.6 引数のデフォルト値:

@_を展開したらデフォルト値を解決する。デフォルト値を他の文で追加しない。
my $cols = exists $args_ref->{cols} ? $args_ref->{cols} : $DEFAULT_WITDH;

1 9.7 スカラーコンテキストでの戻り値:

スカラーを戻す時はreturn scalarを使う。

1 9.8 コンテキストに応じた戻り値:

リストを返すサブルーチンがスカラーコンテキストで呼ばれた時は明白な値を返す。
(配列の数なのか文字列なのかは、Perl組み込み関数でも実はバラバラだったりする。できるだけ分かりやすく想像しやすいスカラーを返す)

1 9.9 マルチコンテキストでの戻り値:

スカラーコンテキストで明白な値をしぼれない時はContextual::Returnを検討する。

1 9.10 プロトタイプ:

サブルーチンプロトタイプは使わない。

1 9.11 暗黙的なリターン:

省略しないで明示的なreturnを使う。

1 9.12 失敗のリターン:

失敗状態を返すには裸のreturnを使う。return undefは使わない。
(例外を使う)

1 10.1 ファイルハンドル:

裸のワードをファイルハンドルに使わない。

1 10.2 間接的なファイルハンドル:

レキシカル変数をファイルハンドルにする。
open my $filehandle, '<', $filename

1 10.3 ファイルハンドルのローカル化:

パッケージスコープのファイルハンドルを使う場合はlocalする。
(基本的にパッケージスコープは使わない)

1 10.4 きちんと開く:

IO::Fileを使うか引数3つのopenを使う。
use IO::File;
my $active = IO::File->new($ACTIVE_LOG, '<')
    or croak "Can't open '$ACTILE_LOG': $OS_ERROR";
open my $stdin, '<', '-' or croak "Can't open stdin: $OS_ERROR";

1 10.5 エラーチェック:

ファイルへのopen, close, printをするときは結果をチェックする。

1 10.6 クリーンアップ:

ファイルハンドルは出来るだけ速く明示的に閉じる。
open my $fh, '<', $config_file
    or croak "Can't open '$config_file': $OS_ERROR";

my @lines = <$fh>; # 読み込んだらすぐ閉じる
close $fh
    or croak "Can't close '$config_file' after reading: $OS_ERROR";

1 10.7 入力ループ:

for (<>)ではなくwhile (<>)を使う。
forはファイルを最後まで読み込んでからループする。whileは1行づつループする。
ただしfor my $n (2..1_000_000_000) {}のような大きな範囲のforループは、実行時評価に最適化されて、999999999個の整数のリストを生成しないので問題は出ない。

1 10.8 行ベースの入力:

ファイル全体を<>で読み込まず、1行ごとのI/Oを使う。
全体を読み込むのはスナップショットが必要な場合や、ファイルが不安定な時や、テキスト処理が複数行に渡る場合だけにする。

1 10.9 単純な丸呑み:

ファイルハンドルをdo{ }ブロックで囲む。
ファイル全体をどうしても一度に読み込む場合はFile::Slurp, sysread, do{ local $/; <$fh> };を使う。
my $code = do { local $/; <$in> };
sysread $fh, $text, -s $fh;

1 10.10 強力な丸呑み:

Perl6::Slurpを使ってストリームを一気に読む。
use Perl6::Slurp;
my $text = slurp $file_handle;
my @lines = slurp $file_name;
my @lines = slurp $file_name, {chomp => 1};

1 10.11 標準入力:

*STDINは使用しない。*ARGVを使う。(<>はデフォルトで<ARGV>になる)

1 10.12 ファイルハンドルへの出力:

printではファイルハンドルを中カッコ{ }で囲む。
print {$file} $name, $rank, $serial_num, "\n";
print {*STDERR} $name, $rank, $serial_num, "\n";
use IO::Handle
$file->print( $name, $rank, $serial_num, "\n" );
*STDERR->print( $name, $rank, $serial_num, "\n" );

1 10.13 単純なプロンプト:

対話形式で入力するときはプロンプトを表示する。

1 10.14 対話性:

プロンプト周りはややこしいので自分で書かない。IO::Interactiveを使う。

1 10.15 強力なプロンプト:

プロンプト表示はIO::Promptを使う。

1 10.16 プログレスインジケータ:

待つ処理が続く時は進行状況を伝える。
print {*STDERR} 'Connecting to server...';

1 10.17 自動プログレスインジケータ:

Smart::Commentsモジュールで###に続けて書いたコメントが自動的に表示されるのを使う。

1 10.18 自動フラッシュ:

selectを使った自動フラッシュは使わない。
自動フラッシュはIO::Handleのautoflush()を使う。
use IO::Handle;
*STDOUT->autoflush();

1 11.1 逆参照:

可能な限り矢印->で逆参照する。
${$list_ref}[0] # NG
ではなく
$list_ref->[0] # Ok
にする。
スライスの時は->は使えない。
@{$list_ref}[0, -1]; # ok
矢印を使うと[ ... ]がスカラーコンテキストになり最後のインデックスだけになる。
$list_ref->[0, -1]; # same ($list_ref->[-1], undef);

1 11.2 中かっこで囲まれた参照:

基本的に参照は中カッコ{ }で囲む。

1 11.3 シンボリック参照:

シンボリック参照は決して使わない。
(myによるレキシカル変数を使ってパッケージ変数は基本的に使わないので、シンボリック参照も使う必要がない)

1 11.4 循環参照:

weakenを使って循環データ構造からくるメモリリークを回避する。
use Scalar::Util qw( weaken );

1 12章 正規表現:

正規表現はPerlとは別のもう一つの言語だと思え。

1 12.1 拡張フォーマット:

いつも/xフラグを使う。
/xフラグが有効だと、正規表現でスペースや改行やインデントによる整形が使えるようになる。#コメントも使える。

1 12.2 行の境界:

いつも/mフラグを使う。

1 12.3 文字列の境界:

文字列の境界アンカーとして\Aと\zを使う。
「文字列の先頭」には\Aを使う。/mフラグで^を使わない。「文字列の末尾」には\zを使う。/mフラグで$を使わない。

1 12.4 文字列の末尾:

「文字列の末尾」には\Zでは無く\zを使う。
\Zのかわりに\n?\z。

1 12.5 任意の文字とのマッチ:

いつも/sフラグを使う。
/sフラグを使えばドット(.)は改行を含むすべての文字とマッチする。
「改行以外の文字とマッチ」は[^\n]を使う。

1 12.6 遅延フラグ:

Regexp::Autoflagsの義務化を検討する

1 12.7 中かっこのデリミタ:

正規表現が複数行になるときは/.../ではなくm{...}を使う。

1 12.8 その他のデリミタ:

/.../かm{...}以外のデリミタをいっさい使わない。

1 12.9 メタ文字:

エスケープされたメタ文字ではなく単数文字クラスを使う。
m/ \{ . \. \d{2} \} /xms; # NG
m/ [{] . [.] \d{2} [}] /xms; # Ok

1 12.10 名前付き文字:

エスケープされたメタ文字ではなく名前付き文字を使う。
use charnames qw( :full );

1 12.11 プロパティ:

[a-zA-Z]などではなく\p{Alphabetic}などのプロパティを使う。
perldoc perlunicode

1 12.12 ホワイトスペース:

特定の空白ではなく任意の空白をマッチさせる。
空白が要求される場所では\s+
空白を使用出来る場所では\s*

1 12.13 制約なしの繰り返し:

出来るだけ多くマッチするときは具体的に書く。
(.*)&よりも(.*?)&
(.*)&よりも([^&]*)

1 12.14 捕捉のためのかっこ:

カッコ( )はキャプチャーのためだけに使う。
選択のためのカッコは(?: )を使ってキャプチャーしない。

1 12.15 捕捉された値:

キャプチャーが成功して$1や$2に値が入ったかどうかはdefined $1を判定しない。
$1などには他の場所でキャプチャーされた値が入っているかもしれない。
$full_name =~ m/\A (Mrs?|Ms|Dr) \s+ (\S+) \s+ (\S+) \z/xms;
if (defined $1) { # NG!
    ($title, $first_name, $last_name) = ($1, $2, $3);
}
こうじゃなくて
if ($full_name =~ m/\A (Mrs?|Ms|Dr) \s+ (\S+) \s+ (\S+) \z/xms) {
    ($title, $first_name, $last_name) = ($1, $2, $3); # Ok
}
こうする

1 12.16 捕捉変数:

キャプチャーしたらすぐに適切な名前の変数に代入する。
my ($opt_name, $operator, $opt_val, $comment)
    = $config =~ m/ \A (\S+) \s* (=|[+]=) \s* ([^;]+) ; \s* \# (.*)/xms;

1 12.17 トークンごとのパターンマッチ:

/gcフラグでトークンに分解する。
\Gで「前回のパターンマッチの終わり」

1 12.18 表形式の正規表現:

配列から正規表現をjoin '|', map {quotemeta $_} reverse sort @_;で生成する

1 12.19 正規表現の生成:

複雑な正規表現は単純な要素に分解して定数に入れる

1 12.20 既製の正規表現:

Regexp::Commonを使う

1 12.21 選択肢:

一文字の選択(a|b|c)のかわりに文字クラス([abc])を使う

1 12.22 選択肢のリファクタリング:

前後の共通部分をまとめる

1 12.23 バックトラック:

バックトラックしない場所は(?>...)をつかう。
my $str = '(foo,bar,baz,hoge,fuga)';

$str =~ m{ [(] $ITEM (?> (?:,$ITEM)* ) [)] }xms;

1 12.24 文字列比較:

1つの正規表現マッチよりも個別にeqでマッチさせるほうが高速。
大文字と小文字を区別しないためだけに/iフラグ正規表現を使うよりも、lc()を使う方が高速。

1 13.1 例外:

失敗の時は、特別な値をreturnしたりフラグを使ったりしないで例外を出す

1 13.2 組み込み関数のエラー:

組み込み関数の失敗でも例外を出す。
Fatalモジュールを使う。
use Fatal qw( open close );

1 13.3 コンテキストに応じたエラー:

全てのコンテキストでエラーの例外だす。
Fatalで:voidマーカーは使わない。

1 13.4 システムエラー:

system関数は成功するとfalse、失敗するとtrueを返すので注意する。
systemを出来るだけ使わずにモジュールを使う。
Perl6::Builtines qw( system )を使う。

1 13.5 回復可能なエラー:

回復可能のエラーを含む全てのエラーで例外を出す。

1 13.6 エラーの報告:

いつもcroak()を使う。

1 13.7 エラーメッセージ:

エラー文は受け手が理解出来るように書く。

1 13.8 エラーの文書化:

1 13.9 オブジェクト指向例外:

データをハンドラに伝える時は例外オブジェクトを使う。

1 13.10 揮発性のエラーメッセージ:

エラー文が変化する可能性がある時は例外オブジェクトを使う。

1 13.11 例外階層:

例外処理が複数の場所にある場合は例外オブジェクトを使う。

1 13.12 例外処理:

例外オブジェクトは派生先から評価する。

1 13.13 例外クラス:

例外オブジェクトを自動的に作る。CPANのException::Classを使う。

1 13.14 例外の展開:

例外変数はレキシカル変数にコピーする。
my $exception = $EVAL_ERROR
Exception::Classのcaught()は$EVAL_ERRORを返すのでそれを代入してもよい。

1 14.1 コマンドラインの構造:

一貫性のあるコマンドラインオプションと引数を使う。

1 14.2 コマンドラインの規則:

標準の規則に従う。

1 14.3 メタオプション:

--helpなどを標準化する。

1 14.4 上書き処理を指定する引数:

入力と出力に同じファイル名を指定出来るようにする。
「unlink 出力ファイル名」の後に出力ファイルをopenする。
IO::InSituモジュールを使う。

1 14.5 コマンドラインの処理:

Getopt::Longを使う。
CPANのGetopt::Cladeを使う。

1 14.6 インターフェイスの一貫性:

インターフェース、ランタイムメッセージ、ドキュメントの一貫性を保つ。
Getopt::Euclidの=for Euclidを使う。

1 14.7 プログラム間の一貫性:

コマンドライン処理の共通機能はモジュールにする。

1 15.1 オブジェクト指向の使用:

オブジェクト指向はデフォルトではなく選択肢にする。

1 15.2 判断基準:

1 15.3 擬似ハッシュ:

擬似ハッシュは使用しない。

1 15.4 制限付きハッシュ:

制限付きハッシュは使用しない。

1 15.5 カプセル化:

ハッシュベースのオブジェクトではなく匿名スカラーでインサイドアウトオブジェクトを使う。
(Class::Accessor::Fastを使ってアクセサを作るのも有りか)

1 15.6 コンストラクタ:

すべてのクラスのコンストラクタの名前はnew()にする。

1 15.7 クローン化:

コンストラクタでオブジェクトを複製しない。
複製が必要ならclone()メソッドを実装する。

1 15.8 デストラクタ:

いつもデストラクタを定義する。
sub DESTROYでdeleteする。

1 15.9 メソッド:

メソッドはサブルーチンと同じガイドラインに従う。
メソッドの方がパラメータが少ない傾向が有る。
サブルーチンと違い、メソッドには組み込み関数と同じ名前を付けても良い。(組み込み関数と同じような機能のときに違う名前を付けると、類推が難しくなる)

1 15.10 アクセサ:

読み取りと書き込みのアクセサを別々に用意する。
get_とset_を使う。
(Class::Accessor::Fastを使うのがいいんじゃないか?)

1 15.11 lvalueアクセサ:

lvalueアクセサは使用しない。

1 15.12 間接的なオブジェクト:

間接的なオブジェクト構文は使わない。
new ObjectではなくObject->new()を使う。

1 15.13 クラスのインターフェイス:

最小限でなく最適なインターフェースを提供する。

1 15.14 演算子のオーバーロード:

演算子のオーバーロードは代数表記と同じ形のものだけにする。

1 15.15 型の強制変換:

オブジェクトをブール、数値、文字列に型変換するオーバーロードを検討する。

1 16.1 継承:

use baseを使う

1 16.2 オブジェクト:

インサイドアウトオブジェクトを使う。

1 16.3 オブジェクトのブレス化:

引数1つのblessを使用しない。

1 16.4 コンストラクタの引数:

コンストラクタの引数にはハッシュ参照を使う。ラベル付きの値を渡す。
sub new {
    my ($class, $arg_ref) = @_;

    my $new_object = bless anon_scalar(), $class;

    $client_num_of(ident $new_object) = $arg_ref->{client_num};
    $name_of(ident $new_object)       = $arg_ref->{client_name};

    return $new_object;
}

1 16.5 基底クラスの初期化:

ハッシュのハッシュを渡して、ベースクラスの引数をクラス名で指定する。
Class::Std::Utils

1 16.6 オブジェクトの生成と破棄:

生成、初期化、破棄のプロセスを分離する。

1 16.7 クラス階層の自動生成:

Class::Stdを使う。

1 16.8 属性の破棄:

デストラクタでClass::Stdで:ATTRを使う。

1 16.9 属性の構築:

初期化にClass::Stdの:ATTR( init_args => 'hoge' );を使う。

1 16.10 強制的な型変換:

強制的な型変換はClass::Stdの:STRINGIFY、:NUMERIFY、:BOOLIFYメソッドとして指定する。

1 16.11 累積メソッド:

SUPER::呼び出しのかわりにClass::Stdの:CUMULATIVEメソッドを使う。

1 16.12 自動的なロード:

AUTOLOAD()を使わない。
Class::StdのAUTOMETHOD()を検討する。

1 17.1 インターフェイス:

モジュールのインターフェースを最初に設計する。

1 17.2 リファクタリング:

重複するコードはサブルーチンにする。重複するサブルーチンはモジュールにする。

1 17.3 バージョン番号:

v1.0.3のvstringを使ってはダメ。
versionモジュールとqv(...)コンストラクタを使う。
use version; our $VERSION = qv('1.0.3');

1 17.4 バージョン要件:

「このバージョン以上じゃないと動作しない」という指定を書く。
use 5.006001;やuse only q( 5.6.1- !5.8.0 );を使う。

1 17.5 エクスポート:

エクスポートは慎重に。必要な場合にだけ使う。
@EXPORTと@EXPORT_OKで分ける。

1 17.6 宣言によるエクスポート:

宣言的なエクスポートを検討する。Perl6::Export::Attrsモジュールを使う。

1 17.7 インターフェイス変数:

モジュールのインターフェースの一部としてパッケージ変数を使わない。

1 17.8 モジュールの作成:

新しいモジュールを作る時はCPANのModule::Starterで自動生成を使う。
Module::Starter::PBPも使う。

1 17.9 標準ライブラリ:

自分でコードを1から書かずに、可能な限り標準ライブラリを使う。
perldoc perlmodlib

1 17.10 CPAN:

CPANモジュールを使用する。

1 18.1 テストケース:

最初にテストケースを作る。
コード本体を書く前にテストコードを書く。

1 18.2 モジュール型のテスト:

Test::Simple、Test::Moreを使ってテストを標準化する。
(今どきだったらTest::Baseか?)

1 18.3 テストスイート:

Test::Harnessを使ってテストスイートを標準化する。
proveコマンドが使える。

1 18.4 失敗:

失敗するテストスイートを作る。

1 18.5 何をテストするか:

起こりそうな事と、起こらなそうな事を両方テストする。
不正な動作を検出するのにふさわしい場所。
  • 有効範囲の最大値と最小値
  • 最小値よりも少し小さい値と、最大値よりも少し大きい値
  • 負数値、正数値、0
  • 非常に小さい負数値、正数値
  • 空の文字列と複数行の文字列
  • "\0"などの制御文字が含まれた文字列
  • ASCII以外の文字列(Latin-1、Unicode)
  • undefとundefのリスト
  • '0', '0E0', '0.0', '0 but true'
  • 空のリスト、空の配列、空のハッシュ
  • 重複する値が含まれたリスト
  • 決して入力される事の無い入力値
  • 必ず利用出来るはずのリソースとのやりとり
  • 数値が期待される場所への数値でない入力、数値が期待されない場所への数値の入力
  • 参照が期待される場所への非参照値。参照が期待されない場所への参照値
  • サブルーチン、メソッドへの引数の不足
  • サブルーチン、メソッドへの余分な引数
  • 順序がバラバラと位置指定の引数
  • 不正なラベルが付いたキーと値の引数
  • モジュールの不適切なバージョンのロード
  • これまで遭遇したことのあるすべてのバグ

1 18.6 デバッグとテスト:

デバッグの前に新しいテストケースを追加する。

1 18.7 制約:

いつもuse strictを使う。

1 18.8 警告:

いつも警告を明示的に表示する。
use warningsを使う。

1 18.9 正確さ:

use strictとuse warningsを使っていて警告が出なくても、正確であると決めつけない。

1 18.10 制約の無効化:

no strict 'refs'などを使う時は最も狭いスコープで使う。

1 18.11 デバッガ:

perlデバッガを習得する。

1 18.12 手動でのデバッグ:

手動でのデバッグはシリアライズされた出力をwarnする。
use Data::Dumper qw( Dumper );
warn Dumper ($results);

1 18.13 半自動デバッグ:

warnではなくSmart::Commentsの###も検討する。
Permalink: http://www.otsune.com/diary/2006/10/13/1.html#200610131
trackback
このエントリーを含むはてなブックマーク del.icio.us livedoor Clip View blog reactions
Last Updated 2006-10-13 00:00:00 By otsune