Perlベストプラクティス/Damian Conway_
目次は oreilly.co.jp_ で。
Internet Archive: Details: YAPC::Asia 2006 Tokyo "Perl Best Practices"_ で、YAPC::Asiaの講演ビデオを見る事が出来る。
1.1.1 堅牢性:
参照の変数名は_ref付きに。
テーブルから正規表現を生成してDRYに。
if-elsif-elsif-elseの連鎖は止めてテーブル参照に。
エラー発生でundefを返さずに例外を出す。
ソースをコピペしないでサブルーチンやモジュールにまとめる。
テーブルから正規表現を生成してDRYに。
if-elsif-elsif-elseの連鎖は止めてテーブル参照に。
エラー発生でundefを返さずに例外を出す。
ソースをコピペしないでサブルーチンやモジュールにまとめる。
2.1 かっこ:
K&Rスタイルで書く。
my @names = (
'hoge',
'fuga',
);
BSDスタイルとGNUスタイルは使わない。
2.2 キーワード:
キーワードと開きカッコのあいだにスペースを入れる。サブルーチンと混同しないように。
for my $result (@results) {
print_sep();
}
2.3 サブルーチンと変数:
サブルーチンや変数名と後続の開きカッコのあいだにスペースを入れない。
2.4 組み込み関数:
組み込み関数や特定の標準モジュールサブルーチンは不要なカッコを使わない。carp, croak, first, max, prompt。
while (my $record = <$results_file>) {
chomp $record;
my ($name, $votes) = split "\t", $record;
print 'Vote for ',
#略
}
サブルーチンとしてカッコを付ける時はあいだにスペースを入れない。
while (my $record = <$results_file>) {
chomp( $record );
my ($name, $votes) = split("\t", $record);
print(
'Vote for ',
#略
);
}
2.5 キーとインデックス:
ハッシュのキーや配列のインデックスと周囲のカッコのあいだにスペースを入れる。
$candidates[$i] = $incumbent{ $candidates[$i]{ get_region() } };
2.6 演算子:
2項演算子の前後にスペースを入れる。優先度の低い演算子の左右に2こ以上のスペースを入れて見やすくする。
単項演算子(「!」や「-」)と変数のあいだはスペースを入れない。
名前付き単項演算子(sin. cos, exp)は関数のようにスペースを入れる。
単項演算子(「!」や「-」)と変数のあいだはスペースを入れない。
名前付き単項演算子(sin. cos, exp)は関数のようにスペースを入れる。
2.7 セミコロン:
ブロックに文が一つしかなくてもセミコロンを付ける。
文が一つだけのmapプロック、grepブロックの場合はセミコロンを省略する。
文が一つだけのmapプロック、grepブロックの場合はセミコロンを省略する。
2.8 コンマ:
複数行リストの値のあとにコンマを入れる。最後の行(値)のあとにもコンマを入れる。
2.9 行の長さ:
一行の文字数は78列まで。
2.10 インデント:
スペース4つのインデントを使う。
2.11 タブ:
タブは使わない。vimは:set expandtabで。
文字としてタブを使う場合は\tで。
文字としてタブを使う場合は\tで。
2.12 ブロック:
1行に1つの文。mapとgrepも。
2.13 チャンク化:
処理ごとに分割して前後に空行を入れて段落にする。段落の先頭に1行コメントを入れる。
2.14 Else:
}とelseは別の行に。
if ($hoge) {
$fuga++;
}
else {
$hige++;
}
2.15 縦の整列:
関連する値は縦に整列させる。
2.16 長い文の分割:
長い式は演算子の前で分割する。
2.17 非終端式:
文の途中に長い式が有る場合は、変数に代入して独立させる。
2.18 優先度による分割:
長い式は最も優先度の低い演算子でわける。
2.19 代入:
長い代入式は=の前でわける。
$predicted_val
= ($minimum + $maximum) / 2
+ $predicted_change * max($fudge_factor, $local_epsilon);
2.20 3項演算子:
長い式の3項演算子は?と:を縦に揃える。
2.21 リスト:
長いリストはカッコで囲む。
my @months = qw(
January February March
April May June
July August September
October November December
);
2.22 自動レイアウト:
perltidyを使う。(今のバージョンのperltidyなら、~/.perltidyrcに-pbpを書くか-pbpを指定すれば良い)
3.1 識別子:
命名規則。
パッケージは<名詞>::<形容詞>::<形容詞>
変数は$<形容詞>_<名詞>もしくは$<名詞>
参照テーブルとして使うハッシュや配列は%<名詞>_<前置詞>。前置詞はofやforなど。
サブルーチンは<動詞>_<名詞>か<動詞>_<形容詞>_<名詞>など。(<動詞>[_<形容詞>]?_<名詞>[_<前置詞>|<分詞>]?)
パッケージは<名詞>::<形容詞>::<形容詞>
変数は$<形容詞>_<名詞>もしくは$<名詞>
参照テーブルとして使うハッシュや配列は%<名詞>_<前置詞>。前置詞はofやforなど。
サブルーチンは<動詞>_<名詞>か<動詞>_<形容詞>_<名詞>など。(<動詞>[_<形容詞>]?_<名詞>[_<前置詞>|<分詞>]?)
3.2 ブール:
is_validやhas_foundなど真偽値にちなんだ名前にする。
3.3 参照変数:
リファレンス変数の名前には_refを付ける。
3.4 配列とハッシュ:
配列は複数形、ハッシュは単数形の名前を付ける。
例外として、参照テーブルとして一つの値を取り出すために使う配列は単数形。
例外として、参照テーブルとして一つの値を取り出すために使う配列は単数形。
3.5 アンダースコア:
単語の区切りはアンダースコアで。キャメルケースは使わない。
3.6 大文字の使い分け:
サブルーチン、メソッド、変数、ラベル付き引数の名前は小文字のみ。
パッケージ、クラスには大文字と小文字を。
定数には大文字のみを。
例外として固有名詞や略語や単位はなじみのある表記に従う。(HTTP、W3C::XHTML、LaTeX、Mbps)
パッケージ、クラスには大文字と小文字を。
定数には大文字のみを。
例外として固有名詞や略語や単位はなじみのある表記に従う。(HTTP、W3C::XHTML、LaTeX、Mbps)
3.7 略記:
省略する時はorigやlenやdescなど先頭を使う。orgnやlnghやdscnなど母音省略はしない。
3.8 意味不明な略記:
省略するのは意味が分かるときだけにする。
3.9 意味不明な名前:
last、set、left、right、no、secondなど、意味が複数ある単語を名前に使わない。
3.10 ユーティリティサブルーチン:
モジュールやクラスの内部専用のサブルーチン名には、先頭に_を付ける。
4.1 文字列デリミタ:
変数展開してほしい時だけダブルクォーテーションの"で囲む。(もしくはqq{ ... })
変数展開が無い場合はシングルクォーテーションの'で囲む。
文字列にシングルクォーテーションが含まれる時はq{ ... }で囲む。(\'は使わない)
文字列にシングルクォーテーションとかっこが含まれる時はq[ ... ]角カッコで囲む。
複数行に文字列がある場合はq{ ... }などの汎用的な囲みで統一する。
変数展開が無い場合はシングルクォーテーションの'で囲む。
文字列にシングルクォーテーションが含まれる時はq{ ... }で囲む。(\'は使わない)
文字列にシングルクォーテーションとかっこが含まれる時はq[ ... ]角カッコで囲む。
複数行に文字列がある場合はq{ ... }などの汎用的な囲みで統一する。
4.2 空の文字列:
空の文字列は''ではなくq{}を使う。
4.3 1文字で構成される文字列:
スペース一つは' 'ではなくq{ }を使う。
タブは"\t"を使う。
'"'や"\""は使わずに、q{"}やq{'}を使う。
join(',', @list)は使わずにjoin(q{,}, @list)を使う。
タブは"\t"を使う。
'"'や"\""は使わずに、q{"}やq{'}を使う。
join(',', @list)は使わずにjoin(q{,}, @list)を使う。
4.4 エスケープ文字:
数値エスケープではなく名前付き文字エスケープを使う。
$escape_seq = "\177\006\030Z"; #これではなく
use charnames qw( :full );
$escape_seq = "\N{DELETE}\N{ACKNOWLEDGE}\N{CANCEL}Z"; #これを使う
4.5 定数:
名前付き定数を使う。use constantは使わない。
use Readonlyを使う。
use Readonlyを使う。
4.6 先頭のゼロ:
10進数の先頭に0を付けない。(8進数になってしまう)
8進数を使う時はoctを使用する。
8進数を使う時はoctを使用する。
4.7 長い数字:
桁の多い数字はアンダースコアで任意に区切れる。
4.8 複数行の文字列:
文字列に\nが含まれていてソースコードが一行に収まらないときは、改行の後で区切る。
$usage = "Usage: $0 <file> [-full]\n"
. "(Use -full option for full dump)\n"
;
4.9 ヒアドキュメント:
文字列が2行を超える時はヒアドキュメントを使う。
4.10 ヒアドキュメントのインデント:
ヒアドキュメントはインデントが崩れるので、サブルーチン(ゼアドキュメント)か定義済み変数にする。
4.11 ヒアドキュメントのターミネータ:
END_で始まる大文字のターミネータを使う。
4.12 ヒアドキュメントの引用符:
変数展開しない場合はシングルクォーテーションの'でターミネータを囲む。
変数展開する場合はダブルクォーテーションの"で囲む。クォーテーションの省略はしない。
変数展開する場合はダブルクォーテーションの"で囲む。クォーテーションの省略はしない。
4.13 裸のワード:
ベアワードは使わない。use strict;を使う。
4.14 ファットコンマ:
ファットコンマの=>はペアの時に使う。
%default_service_record = {
name => '<unkown>',
rank => 'Recruit',
}
サブルーチンに名前付き引き数を渡すときに使う。
$text = format_text ({ src=>$raw_text, margins=>[1,62] });
定数を作成するときに使う。
Readonly my $ESCAPE_SEQ => "\N{DELETE}\N{ACKNOWLEDGE}\N{CANCEL}Z";
4.15 シンコンマ:
スカラーコンマは使わない。doとセミコロンを使う。コンマはリスト項目を分割する事にだけ使う。
4.16 優先度の低い演算子:
優先度の高い!演算子と、優先度の低い論理否定notを混在させない。
andとnotはいっさい使わない。
orはcroakなど例外を送出するときに使う。
andとnotはいっさい使わない。
orはcroakなど例外を送出するときに使う。
4.17 リスト:
リストは全てカッコで囲む。
カッコ( )のかわりに間違えて角カッコの[ ]を使うと匿名配列になってしまうので注意。
カッコ( )のかわりに間違えて角カッコの[ ]を使うと匿名配列になってしまうので注意。
4.18 リストのメンバーシップ:
文字列リストの有無はハッシュテーブルで。
その他リストの有無はList::MoreUtilsのany()で。
その他リストの有無はList::MoreUtilsのany()で。
5.1 レキシカル変数:
どうしても必要なとき以外はmyによるレキシカル変数だけを使う。
5.2 パッケージ変数:
パッケージ変数は使用しない。
(アクセサを使ってレキシカル変数を使う)
(アクセサを使ってレキシカル変数を使う)
5.3 ローカル化:
パッケージ変数をやむを得ず変更する時はlocalを使う。
5.4 初期化:
5.5 句読点変数:
use English;
5.6 句読点変数のローカル化:
5.7 マッチ変数:
正規表現のマッチ変数($` $& $' $PREMATCH $MATCH $POSTMATCH)はスコープがグローバルでどこで書き変わったのか混乱するので絶対に使用してはならない。
Regexp::MatchContextモジュールを使う。
Regexp::MatchContextモジュールを使う。
5.8 ドル記号とアンダースコア:
$_の乱用は混乱の元。
for ( @_ ? @_ : $_ ) {
s{hoge}{}xms; # これは良くない
}
ではなくて
for my $orig_args ( @_ ? @_ : $_ ) {
$orig_args =~ s{hoge}{}xms;# こうする
}
5.9 配列のインデックス:
配列を最後から数える時はマイナスのインデックスを使う。
5.10 スライス:
配列スライスやハッシュスライスを利用する。
@hoge[1..10]は1から10。
@hoge[-1..-9]はダメ(空リストになる)。@hoge[-9..-1]はok。
@frames[-1,-2,-3];
@active{'top', 'prev', 'backup'};
は
($frames[-1], $frames[-2], $frames[-3]);
($active{'top'}, $active{'prev'}, $active{'backup'});
と同じ。@hoge[1..10]は1から10。
@hoge[-1..-9]はダメ(空リストになる)。@hoge[-9..-1]はok。
5.11 スライスのレイアウト:
スライスからスライスへの代入の時は項目ごとに縦に揃える。
5.12 スライスのファクタリング:
スライスのキーやインデックスが多い時はハッシュにまとめる。
6.1 ifブロック:
基本として、後置きのifではなくプロック形式の前置きifを使う。
6.2 ポストフィックスセレクタ:
例外としてnext, last, redo, return, goto, die, croak, throwの時は後置きifを使う。
6.3 ほかのポストフィックス修飾子:
後置きのunless, for, while, untilを使わない。
6.4 否定制御文:
unless, untilは使わない。
特にnotや!が含まれた二重否定や、不等号を含んだunlessは絶対に使わない。
ifを使う。
特にnotや!が含まれた二重否定や、不等号を含んだunlessは絶対に使わない。
ifを使う。
6.5 Cスタイルのループ:
for (my $i=1; $i<=$MAX; $i++)という3部構成のCスタイルのforは使わない。
6.6 不要な添え字:
ループで配列やハッシュのインデックスを使わない。
配列を直接ループさせる。
配列を直接ループさせる。
for my $client (@clients) {
$client->hoge(); # ok
}
インデックスのループは重いからダメ。
for my $n (0..$#clients) {
$clients[$n]->hoge(); # 重い
}
ハッシュはvaluesをループさせる。(valuesはコピーのリストではなくエイリアスのリストが返る)
for my $trans_word (values %trans_for) {
if ( $trans_word =~ m/hoge/xms) {
$trans_word = 'FUGA'; # ok
}
}
キーでループすると重いからダメ。
for my $orig_word (keys %trans_for) {
if ( $trans_for{$orig_word} =~ m/hoge/xms) {
$trans_for{$orig_word} = 'FUGA'; # 重い
}
}
6.7 必要な添え字:
ループ内では添字を1回以上指定しない。
必要な時はData::Aliasを使う。
必要な時はData::Aliasを使う。
6.8 反復子変数:
for, whileは$_ではなくmy $hogeで名前付きレキシカル変数を使う。
6.9 非レキシカルループ反復子:
forの変数は必ずmyを使う。
6.10 リストの生成:
リストから新しいリストを生成するときはforじゃなくmapを使う。
my @sqrt_results = map { sqrt $_ } @results;
6.11 リスト選択:
リストから不要な要素を削る時はgrepを使う。
リストから特定の値を検索するときはgrepかList::Utilのfirstを使う。
リストから特定の値を検索するときはgrepかList::Utilのfirstを使う。
6.12 リスト変換:
リストをその場で変換する時はforを使う。
@temperature = map { F_to_K($_) } @temperature; # 重い
for my $measurement (@temperature) {
$measurement = F_to_K($measurement); # ok
}
6.13 複雑なマッピング:
複雑なリスト変換はサブルーチン呼び出しにする。
6.14 リスト処理の副作用:
リスト関数で$_を変更しない。
6.15 マルチパート選択:
if-elsif-elsif-elseを連鎖させない。
6.16 値の交換:
matchのif連鎖はやめてテーブル参照にする。
6.17 表形式の3項演算子:
ifの連鎖のかわりに?:の3項演算子の連鎖を使う。
6.18 do-whileループ:
do-whileは使わない。
6.19 線形コーディング:
ループ内では除外条件を先に判定する。すべての項目を計算したあとで、まとめて判定するのではなく、計算項目ごとに判定する。
6.20 分散制御:
構造化しすぎで無理にループ終了を一元化しない。
6.21 やり直し:
whileではなくforやredoを使う。
6.22 ループラベル:
ループにラベルをつけて、next, last, redoで使う。
7.1 ドキュメントの種類:
ユーザーむけドキュメント、テクニカルドキュメントを区別して書く。
7.2 ひな形:
PODのテンプレートを使う。
7.3 拡張ひな形:
7.4 場所:
PODはソースと同じファイルに入れる。
7.5 近接性:
ドキュメントは一カ所にまとめる。
7.6 位置:
PODはファイルの最後におく。
7.7 テクニカルドキュメント:
開発者向けドキュメントは適当に分割する。
7.8 コメント:
プロックコメントテンプレートを使う。
7.9 アルゴリズムのドキュメント:
アルゴリズムの説明に1行コメントを入れる。
7.10 補足のためのドキュメント:
難しい部分は行末コメントを入れる。
7.11 防御的なドキュメント:
迷ったり悩んだところはコメントを入れる。
7.12 暗示的なドキュメント:
コメントを付ける必要があると思ったらコードを分かりやすく書き換えることを検討する。
分かりにくいところは事実を端的に述べるコメントを入れる。
分かりにくいところは事実を端的に述べるコメントを入れる。
7.13 言説的なドキュメント:
長いテクニカルドキュメントを書く時は=for =cutのPODを使う。
複数の段落やサンプルコードの埋め込みをしたい時は=begin =end =cutを使う。
複数の段落やサンプルコードの埋め込みをしたい時は=begin =end =cutを使う。
7.14 校正:
PODはperldocなどで良く読み返して誤字脱字や分かりにくい文章を修正する。



[ コメントする ]