Top > MyPage
 

Perlベストプラクティス メモ

ベストプラクティス

省略

コードのレイアウト

かっこ

K&Rスタイルを使用する。

if ( $tmp =~ /../) {
                 #^^
}

のように中括弧を配置する。

if ( $tmp =~ /../)
{
   ....
}

if ( $tmp =~ /../)
  {
   ....
  }

は使用しない。

キーワード

制御キーワードを後続の小括弧()から分離する。

if ( $tmp =~ /../ ) {
 #^
}


while ($min < $max) {
    #^
}

のように分離する。

サブルーチンと変数

サブルーチンまたは変数の名前を後続の括弧から分離しない。

$array[$i] = $hash{$key};
&method($arg);

のようにし、

$array [$i] = $hash{$key};
     #^
&method ($arg);
      #^

のようには分離しない。

組み込み関数

組み込み関数や「名誉」組み込み関数のために不要な括弧を使用しない。

これはどちらかというと好みじゃないので、省略。むしろ、どこまでが引数なのかをはっきりさせるために、括弧をつける。その代わり、サブルーチンの場合は&を付けて、組み込み関数と区別する方が良い気がしている。

my ($prefecture, $city) = split("\t", $record);
&my_method($city);

キーとインデックス

複合キーやインデックスの周囲の括弧から分離する。

$person = $users{ $persons[$i]{ $p->get_id() } };
                #^             ^            ^ ^

のように、どっからどこまでがどの変数のインデックスなのか等をはっきりさせる。

演算子

スペースで、2項演算子をオペランドから際立たせる。

$number = $i * $j + ($j / 2) * $k;
           #^    ^ ^   ^ ^  ^ ^

のように、スペースを入れる。

セミコロン

なくても大丈夫な場合でも、行末にはセミコロンを入れる。

if ($tmp =~ /(\w)+/) {
    push @array, $1;
                  #^なくてもエラーにはならない
}

のように、エラーにならない場合でも、必ず書く。

コンマ

複数行にまたがるリストの各値の後にコンマを配置する。

my @array = (
   'sakai',
   'toda',
   'chiku',
   'iwane',
   'shibata',
   'kurosawa',
);

のように、後ろにコンマを入れ、最後のは必須ではないが入れておく。最後のに入れておくと、順番を入れ替えたり、後に追加したりした場合に、コンマを追加したりする必要がなく便利。

my @array = (
   'kurosawa',
   'toda',
   'iwane',
   'chiku',
   'shibata',
   'sakai',
);

行の長さ

78桁の行を使用する。

インデント

4列のインデントレベルを使用する。

スペースを使って、4個分のインデントにする。

package Id;
use strict;
use warnings;
use Carp;
use Exception::Class::TryCatch;
use Class::Std;
{
    my %id : ATTR(:init_arg<id>);

    sub get_id() {
        my ($self) = @_;
        my $i = $id{ ident $self};
        if ( !defined($i) || $i eq "" ) {
            IdException->throw( message => 'id is undef or empty!' );
            return;
        }

        if ( $i !~ /^[\d]+$/ ) {
            IdException->throw( message => 'id is not numeric! id=' . $i );
            return;
        }
        return $i;
    }
}
1;

という感じ。

タブ

前項に吸収。

ブロック

2つの文を1行にまとめない。

文字通り。

チャンク化

コードを段落に分ける。

意味の塊を意識して、塊の間は空行を入れず、意味が変わる際には空行を入れる。また、その塊毎にコメントを入れる。

#性別
my $sex;
my $sex_num = $personal->sex;
if ($sex_num == 0) {
  $sex = "男";
} elsif ($sex_num == 1) {
  $sex = "女";
} else {
  $sex = "未記入";
}
$vars{sex} = $sex;

#フリガナ
my $furigana = $personal->kana;
$vars{kana} = $furigana;

#お名前
my $name = $personal->name;
$vars{name} = $name;

#誕生日
my $birthday = $personal->birthday;
$vars{birthday} = $birthday;

という感じ。

else

}とelseを同じ行に並べない。

} else {

とは書かず、

}
else {

と書く。

縦の整列

対の項目は立てに整列させる。

%words = (
    "fred",  "camel",  "barney", "llama", "betty", "oyster",
    "wilma", "oyster", "kaz",    "candy"
);

だったり、

eval {
    $ddd1 = DateTime->new(
        year  => $d1[0],
        month => $d1[1],
        day   => $d1[2],
    );

    $ddd2 = DateTime->new(
        year  => $d2[0],
        month => $d2[1],
        day   => $d2[2],
    );
};

だったり、

if (   !defined($arg_ref)
    || !defined( $arg_ref->{data} )
    || !$arg_ref->{data}
    || ref( $arg_ref->{data} ) ne "HASH" )
{
    ArgException->throw( args => [] );
}

のようにする。

長い文の分割

長い式は演算子の前で分割する。

push @steps, $steps[-1]
             + $radial_velocity * $elapsed_time
             + $ordinal_velocity * ($phase + $phase_shift)
             - $DRAG_COEFF * $altitude
             ;

のようにする。

非終端式

文の途中にある長い式を抽出する。

前項は長い式が最後の場合で、もし長い式が途中にある場合は、その部分を独立させる。

&add_step( \@steps, $steps[-1]
                    + $radial_velocity * $elapsed_time
                    + $ordinal_velocity * ($phase + $phase_shift)
                    - $DRAG_COEFF * $altitude
                    , $elapsed_time);

ではなく、

$next_step = $steps[-1]
             + $radial_velocity * $elapsed_time
             + $ordinal_velocity * ($phase + $phase_shift)
             - $DRAG_COEFF * $altitude
             ;

&add_step( \@steps, $next_step, $elapsed_time);

のように書くこと。

優先順位による分割

長い式は常にもっとも湯煎度の低い演算子で分割する。

push @steps, $steps[-1] + $radial_velocity
             * $elapsed_time + $ordinal_velocity
             * ($phase + $phase_shift) - $DRAG_COEFF
             * $altitude
             ;

ではなく、

push @steps, $steps[-1]
             + $radial_velocity * $elapsed_time
             + $ordinal_velocity
                 * ($phase + $phase_shift)
             - $DRAG_COEFF * $altitude
             ;

のように書くこと。

代入

長い代入式は代入演算子の前で分割する。

$predicted_val = $average
                 + $predicted_change * $fudge_factor
                 ;

でなく、

$predicted_val
    = $average
      + $predicted_change * $fudge_factor
    ;

のように書く。

3項演算子

my $salute = $name eq $EMPTY_STR                     ? 'Customer'
           : $name =~ m/\A((?:Sir|Dame) \s+ \S+)/xms ? $1
           : $name =~ m/(.*), \s+ Ph[.]?D \z    /xms ? "Dr $1"
           :                                         $name
           ;

のように書くこと。

リスト

長いリストは括弧で囲む。

for my $item () {
    push @items, (
       "A brand new $item",
       "A fully refurbished $item",
       "a ratty old $item",
    );
}

のように書く。

自動レイアウト

選択したレイアウトスタイルを機械的に適用する。

perltidyを利用して、何も考えずにレイアウトを任せる。

-l=78 -i=4 -ci=4 -st -se -vt=2 -cti=0 -pt=1 -bt=1 -sbt=1 -bbt=1 -nsfs -nolq \
    -wbb='% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= \
    -= /= |= >>= ||= .= %= ^= x='

というオプションを付けると、今まで書いたほとんどが自動でレイアウトされる。