Perl編碼規(guī)范

1.命名規(guī)則

文件命名

文件名稱統(tǒng)一用英文字母(大小寫)居扒、數(shù)字和下劃線的組合概漱,長度一般不超過20個字符,文件命名體現(xiàn)功能的含義喜喂,正式發(fā)布版本不能加入作者信息瓤摧。Perl Scripts 文件的擴(kuò)展名必須是".pl",Perl Module文件的擴(kuò)展名必須是".pm"玉吁。
例如:

lucent_file_parser.pl
lucent_used_module.pm
標(biāo)識符

采用語法模板來定義標(biāo)識符的名字照弥,命名必須有一定的實際意義,由英文字母組成进副,中間可以根據(jù)語義的連續(xù)性这揣,使用下劃線連接。
(1)變量
局部變量必須由小寫字母和下劃線組成影斑,常量名必須由大寫字母和下劃線組成给赞。由多個單詞組成的名字里,使用下劃線""把多個單詞分開矫户。全局變量以’g’開頭片迅,其余部分的命名規(guī)則和局部變量相同。每個全局變量必須有注釋說明其作用皆辽。
use strict語句稱為pragma柑蛇,它放在腳本的開頭,它會強(qiáng)制我們在定義變量時使用my關(guān)鍵字聲明變量驱闷。my關(guān)鍵字將變量的范圍限制為局部唯蝶。它使代碼更易讀,更不容易出錯遗嗽。如果你沒有使用my關(guān)鍵字聲明變量,那么創(chuàng)建的變量將是全局的鼓蜒,盡量避免使用痹换,這樣可以將變量的范圍縮小到需要它的位置征字。
盡量不要使用過于簡短的變量簡寫(除非是標(biāo)準(zhǔn)的簡寫模式)。
盡量不要使用如$x,$y等意義不太明確的名稱娇豫。
盡量不要使用太長的變量名稱匙姜。
例如:
my $next_node;
(2)包和類
包、類的命名采用大小寫混合冯痢、首字母大寫的方法氮昧。
例如:
IO::Controller
(3)標(biāo)識符縮寫
標(biāo)識符縮寫時要保留單詞的開始字母,不是輔音字母的簡寫浦楣。
例如:

    use List::Util qw( max );
    DESC:
    for my $desc (@orig_strs) {
        my $len = length($desc); # $len來自length
        next DESC if ($len > $UPPER_LIM);
        $max_len = max($max_len, $len);
    }

(4)函數(shù)
由小寫字母袖肥、下劃線組成。
例如:

sub max
{
   ……
}
sub get_msc_name
{
  ……
}
布爾類型

boolean類型的變量振劳,或返回boolean類型的值的函數(shù)椎组,在命名時要反映其屬性,必須用is或者h(yuǎn)as開頭历恐。
例如:

    sub is_valid;
    sub is_metadata_available_for;
    sub has_end_tag;
    my $has_loading_finished;
    my $has_found_bad_record;
數(shù)組和哈希

數(shù)組類型的變量采用復(fù)數(shù)寸癌,hash類型的變量采用單數(shù)。要用undef顯式釋放變量空間弱贼。
例如:

    my @events;
    my @handlers;
    my @unknowns;
    my %option;
    my %title_of;
    my %is_available;

2.注釋

所有注釋可用英文或中文書寫蒸苇,盡量使用英文注釋。保持注釋和代碼的完全一致吮旅,修改程序時溪烤,必須修改相應(yīng)的注釋。注釋的行數(shù)一般應(yīng)在程序總行數(shù)的1/5到1/3鸟辅。禁止出現(xiàn)錯別字氛什。注釋應(yīng)該語義明確然低,避免出現(xiàn)二義性机错。

文件頭部注釋

每個含有源代碼的文件必須在文件開始有關(guān)于該文件的介紹性注釋。其中列出文件名藕咏、創(chuàng)建者再层、創(chuàng)建日期贸铜、功能描述、版本信息聂受、版權(quán)聲明蒿秦;如果對文件進(jìn)行了修改,應(yīng)該在文件頭中說明修改人蛋济、修改日期棍鳖、修改原因,并變更文件的版本信息,最新版本信息放到最前面渡处。
格式為:

#*********************************************************
# FileName: lucent_file_parser.pl
# Creator: Phonix <phonix@gmail.com.cn>
# Create Time: 2006-01-09
# Description: This is the proof-of-concept code for the
#           Windows denial-of-serice attack described by
#           the Razor team (NTBugtraq, 19-May-00).
# CopyRight: Copyright ? Bright Ocean Inter-Telecomm镜悉,All rights reserved.
# Revision: V1.0.0
# ModifyList:
#      Revision: V1.1.1
#      Modifier: Phonix 
#   ModifyTime: 2006-01-17
#   ModifyReason: fix the bug of ……
#
#   Revision: V1.1.0
#   Modifier: Phonix
#   ModifyTime: 2006-01-16
#   ModifyReason: add mysql&oracle db support
#*********************************************************
文件中注釋

建議在文件中標(biāo)識出修改部分的起止位置。
例如:

# add mysql&oracle db support begin
    ……
# add mysql&oracle db support end
函數(shù)注釋

在每個函數(shù)前必須寫描述性注釋医瘫。說明這個函數(shù)的功能侣肄、參數(shù)和函數(shù)的返回值。
格式為:

#*******************************************************************
# Function Name: calc_time($datetime, $delta)
# Description: This function calculate the new datetime. 
# Parameters:
#   1. $datetime is the base time, taking the format of 'yyyy-mm-dd hh:mm:ss'
#   2. $delta is the time which should be add to the $datetime. A positive value increase the time
#      while the negative vale decrease the time
# Return:
#      A new time string is returned, also taking the format of 'yyyy-mm-dd hh:mm:ss' 
#*********************************************************************
程序塊注釋

程序塊注釋用于說明程序中的關(guān)鍵算法醇份、使用某種技巧的代碼以及修改稼锅、測試、閱讀時必須加以注意的代碼僚纷。
格式為:

#*********************************************************************
#注釋內(nèi)容
#......
#********************************************************************
語句注釋

用于對特定程序語句進(jìn)行說明矩距,建議采取在語句行末尾說明的方法,同時注釋換行后也要對齊畔濒。格式為:

    my @names = (
        'Damian',    # Primary key
                    # the key is 
        'Matthew',   # Disambiguator
        'Conway',   # General class or category
    );

3.代碼布局

括號

建議括號剩晴、插入語可以采用兩種方式之一,但是在一個程序里選定那種方式之后侵状,那么要至始至終保持一致赞弥。
(1)方式一
格式為:

    my @names = (
        'Damian',    # Primary key
        'Matthew',   # Disambiguator
        'Conway',    # General class or category
    );
    for my $name (@names) {
        for my $word ( anagrams_of(lc $name) ) {
            print "$word\n";
        }
    }

(2)方式二
括號對{}對必須位于同一列,獨占一行趣兄,并且和{}之外的語句行對齊

    my @names =
    (
        'Damian',   # Primary key
        'Matthew',  # Disambiguator
        'Conway',  # General class or category
    );
    for my $name (@names)
    {
        for my $word (anagrams_of(lc $name))
        {
            print "$word\n";
        }
    }
關(guān)鍵字

把關(guān)鍵字和其他的內(nèi)容分開绽左,關(guān)鍵字if, while, for,else…后面必須接一個空格。ifwhile語句必須使用’{‘和’}’括起語句體艇潭,即使只有一行代碼拼窥。建議不使用單行的if語句。
例如:

    for my $result (@results) {
        print_sep( );
        print $result;
    }
    while ($min < $max) {
        my $try = ($max - $min) / 2;
        if ($value[$try] < $target) {
            $max = $try;
        }
        else {
            $min = $try;
        }
    }
    if ($condition){
      $i++;
    }
子程序和變量

不要把子程序或變量和其后的括號部分分開蹋凝。
例如:

my @candidates = get_candidates($marker);#正確
my @candidates = get_candidates ($marker);#錯誤
代碼縮排

縮進(jìn)采用四個空格鲁纠,或一個TAB(1 TAB 設(shè)置成四個空格)。

代碼塊

不要把兩句話放在一行鳍寂,每行只能寫一個語句改含。
例如:

chomp $record;                                        #正確
next RECORD if $record eq $EMPTY_STR;                 #正確
chomp $record; next RECORD if $record eq $EMPTY_STR;  #錯誤
代碼長度

每個函數(shù)體的語句行不能超過100行(不包括注釋,一個分號算一行)迄汛。每行長度不要超過78個字符捍壤,超過該長度時,必須考慮換行鞍爱,從低優(yōu)先級的操作符處分割長表達(dá)式, 在賦值符前斷開長的語句鹃觉。
例如:
正確:

push (@steps, $steps[-1]
                 + $radial_velocity * $elapsed_time
                 + $orbital_velocity * ($phase + $phase_shift)
                 - $DRAG_COEFF * $altitude);
$predicted_val = $average + $predicted_change * $fudge_factor;

錯誤:

push (@steps, $steps[-1] + $radial_velocity
                 * $elapsed_time + $orbital_velocity
                 * ($phase + $phase_shift) - $DRAG_COEFF
                 * $altitude);
$predicted_val = $average
                     + $predicted_change * $fudge_factor;
操作符

二元運算符(算術(shù)運算符, 賦值運算符等)的兩邊都要接空格,低級操作符(如:+-)兩邊各有兩個空格睹逃,高級操作符(如:*%)兩邊各有一個空格盗扇。盡量使用andor而不要使用&&||,請注意他們的區(qū)別。
在運算符'->'兩邊不要使用空格疗隶,在一元操作符和操作數(shù)兩邊不要使用空格躬柬。
可以使用括號來表示運算的先后順序。
例如:
正確:

my $displacement
        = $initial_velocity * $time  +  0.5 * $acceleration * $time**2;
my $price
        = $coupon_paid * $exp_rate  +  ($face_val + $coupon_paid) * $exp_rate**2;

錯誤:

my $displacement=$initial_velocity*$time+0.5*$acceleration*$time**2;
my $price=$coupon_paid*$exp_rate+(($face_val+$coupon_val)*$exp_rate**2);
語句結(jié)束符

在每個語句后邊要填加分號抽减,分號之前盡量不加空格。
例如:

while (my $line = <>) {
        chomp $line;
        if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {
            push @comments, $2;
        }
        print $line;
    }
代碼排列

數(shù)組或Hash的賦值采用垂直排列橄碾。
例如:
正確:

my @months = qw(
        January   February   March
        April     May        June
        July      August     September
        October   November   December
    );
    my %expansion_of = (
        q{it's}    => q{it is},
        q{we're}   => q{we are},
        q{didn't}  => q{did not},
        q{must've} => q{must have},
        q{I'll}    => q{I will},
    );

錯誤:

my @months = qw(
        January February March April May June July August September
        October November December
    );
my %expansion_of = (
        q{it's} => q{it is}, q{we're} => q{we are}, q{didn't} => q{did not},
        q{must've} => q{must have}, q{I'll} => q{I will},
    );

非末端表達(dá)式

采用中間變量代替長表達(dá)式卵沉。
例如:
正確:

my $next_step = $steps[-1]
                    + $radial_velocity * $elapsed_time
                    + $orbital_velocity * ($phase + $phase_shift)
                    - $DRAG_COEFF * $altitude
                    ;
    add_step( \@steps, $next_step, $elapsed_time);

錯誤:

    add_step( \@steps, $steps[-1]
                       + $radial_velocity * $elapsed_time
                       + $orbital_velocity * ($phase + $phase_shift)
                       - $DRAG_COEFF * $altitude
                       , $elapsed_time);
功能塊順序

在每個Perl Scripts中,每個功能塊之間必須有一個空行法牲。主程序為main()函數(shù)史汗,功能塊出現(xiàn)順序如下:

use modules;

global variable 定義

main定義

sub routine 定義

4.數(shù)值和表達(dá)式

字符串界定符

需要用變量替換的字符串用雙引號,否則用單引號拒垃。
例如:

my $spam_name = "$title $first_name $surname";
my $pay_rate  = "$minimal for maximal work";
my $spam_name = 'Dr Lawrence Mwalle';
my $pay_rate  = '$minimal for maximal work';
常量

使用字符常量停撞,而不要直接用數(shù)值。
例如:
正確:

use Readonly;
    Readonly my $MOLYBDENUM_ATOMIC_NUMBER => 42;
    # and later...
print $count * $MOLYBDENUM_ATOMIC_NUMBER;

錯誤:

print $count * 42;
字符串

(1)兩行
對于兩行的字符串悼瓮,要用“.”進(jìn)行連接戈毒。
例如:
正確:

$usage = "Usage: $0 <file> [-full]\n"
. "(Use -full option for full dump)\n";

錯誤:

$usage = "Usage: $0 <file> [-full]
(Use -full option for full dump)";

(2)多于兩行
對于多于兩行,要采用如下格式横堡,例如:
正確:

    $usage = <<"END_USAGE";
    Usage: $0 <file> [-full] [-o] [-beans]
    Options:
        -full  : produce a full dump
        -o     : dump in octal
        -beans : source is Java
    END_USAGE

錯誤:

    $usage = "Usage: $0 <file> [-full] [-o] [-beans]\n"
             . "Options:\n"
             . "    -full  : produce a full dump\n"
             . "    -o     : dump in octal\n"
             . "    -beans : source is Java\n"
             ;
哈希變量

Hash變量的定義采用雙箭頭(=>)方式埋市。
例如:
正確:

    %default_service_record  = (
        name    => '<unknown>',
        rank    => 'Recruit',
        serial  => undef,
        unit    => ['Training platoon'],
        duty    => ['Basic training'],
    );

錯誤:

    %default_service_record  = (
        'name',   '<unknown>',
        'rank',   'Recruit',
        'serial', undef,
        'unit',   ['Training platoon'],
        'duty',   ['Basic training'],
    );

5.函數(shù)

調(diào)用語法

調(diào)用時要使用圓括號,不管是否有參數(shù)命贴。
例如:

fix();
coerce($input, $INTEGER, $ROUND_ZERO);
函數(shù)返回

在函數(shù)中要進(jìn)行顯式的return返回道宅。
例如:

    sub set_terseness {
        my ($terseness) = @_;
        my $default_terseness = $terseness;
        return;  # Explicitly return nothing meaningful
    }

6.編程慣例

使用use strict

所有Perl Scripts 文件中必須在開始使用“use strict;”,進(jìn)行嚴(yán)格的語法檢查胸蛛,便于查找錯誤污茵。

避免使用內(nèi)部變量名稱

避免使用Perl內(nèi)部變量。使用“use English;”裝入Perl內(nèi)部變量的符號名稱葬项。使用my來限定變量的作用域泞当。下面是一些Perl內(nèi)部變量名稱的對應(yīng)關(guān)系。

      $_      $ARG
      @_      @ARG
      $!      $ERRNO
      $?      $CHILD_ERROR
      $$      $PID
      $0      $PROGRAM_NAME
      $.      $INPUT_LINE_NUMBER
      $|      $OUTPUT_AUTOFLUSH
      $@      $EVEL_ERROR
      $&      $MATCH
      $`      $PREMATCH
      $'      $POSTMATCH
      $+      $LAST_PAREN_MATCH
      $/      $RS
      $\      $ORS
      $<      $UID
      $>      $EUID
      $(      $GID
      $)      $EGID
      $]      $PERL_VERSION
      $?      $CHILD_ERROR
避免使用goto

避免使用goto語句(只有在從多重循環(huán)的內(nèi)部跳出時才可以使用)玷室。除非能夠特別有效的增加程序的效率并且不影響程序良好結(jié)構(gòu)的特殊情況零蓉。

語法檢查(輔助工具)

使用-cw選項檢查Perl程序的語法。
正確:

perl -cw -Mdiagnostics file.pl             # check syntax with warnings on
nt;       # Perl 5.004_04, define constants
use Env;          # instead of $ENV{'HOME'}; Shortens the usage, but do not 
# mix normal variables 
# with environment variables.
使用標(biāo)準(zhǔn)模塊

盡量使用標(biāo)準(zhǔn)庫函數(shù)穷缤、公共函數(shù)和開發(fā)庫中已有的函數(shù)和模塊敌蜂,使用FileHandle模塊來處理文件的讀寫。盡量使用以下的標(biāo)準(zhǔn)Perl模塊:

use strict;         # helps you to locate syntax errors or uncertainties.
use integer;        # if you don't need floating point math津肛,it will speed Perl up.
use constagives you `carp' and `croak'
use English;        # gives symbolic names, like $! ==> $ERRNO
use Getopt::Long;   # --posix command line option handling
use Cwd;           # platform independent cwd()
use File::Basename;  # don't invent your own wheel of this.
use File::Find;       # don't use system("find . -name ...")...
use File::copy;      # don't use system("cp this that");
use File::patch;      # instead of system("mkdir");
use File::stat;       # readable: $st = stat($file), $st->mode
use DirHandle;      # OO form of `readdir'
use Text::Tabs       # un/expand tabs in text
use Text::ParseWords; # Parse text into tokens, understands embedded
                         # quotes. @a = &quotewords("[ +]", 0, $_);
                         # a+b, "a b" + c
use Socket;         # socket handling
use Sys::Hostname;  # don't invent your own wheel
use Net::Ping       # unix ping, check if host is online
use Time::Local     # time manipulations
其他

1章喉、編碼、測試、注釋秸脱,是程序員的三項基本工作落包,它們是同等重要的。
2摊唇、可靠性第一咐蝇,可讀性第二,效率第三巷查。只有在極個別必須強(qiáng)調(diào)效率的部分有序,可以是可靠性第一,效率第二岛请,可讀性第三旭寿。
3、首先是正確崇败,其次是優(yōu)美盅称。
4、無法證明你的程序沒有錯誤后室。因此缩膝,在新編寫完一段程序后,應(yīng)該測試通過后再繼續(xù)編碼咧擂。
5逞盆、改正一個錯誤的同時,可能會引起新的錯誤松申。因此云芦,在修改bug前,首先考慮對其他程序的影響贸桶。修改后舅逸,應(yīng)該對程序進(jìn)行完整的測試,而不是只對修改部分進(jìn)行測試皇筛。
6琉历、避免使用很多個參數(shù)的函數(shù)。
7水醋、函數(shù)應(yīng)該只有一個出口旗笔。
8、循環(huán)應(yīng)該只有一個出口拄踪,避免多個出口蝇恶。
9、復(fù)雜的下標(biāo)使用適當(dāng)?shù)目崭瘛?br> 10惶桐、在盡可能小的作用域內(nèi)定義和使用變量撮弧。
11潘懊、使用括號,表達(dá)復(fù)雜表達(dá)式中的操作符的優(yōu)先順序贿衍。
12授舟、循環(huán)、分支不要超過五個層次贸辈。
13释树、循環(huán)、分支等語句后擎淤,即使只有一行代碼時躏哩,也要使用{}將其括起來。
14揉燃、禁止else gotoelse return
15筋栋、重復(fù)使用的炊汤、完成相對獨立功能的算法、代碼弊攘,應(yīng)該抽象為公共模塊抢腐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市襟交,隨后出現(xiàn)的幾起案子迈倍,更是在濱河造成了極大的恐慌,老刑警劉巖捣域,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啼染,死亡現(xiàn)場離奇詭異,居然都是意外死亡焕梅,警方通過查閱死者的電腦和手機(jī)迹鹅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贞言,“玉大人斜棚,你說我怎么就攤上這事「么埃” “怎么了弟蚀?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酗失。 經(jīng)常有香客問我义钉,道長,這世上最難降的妖魔是什么级零? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任断医,我火速辦了婚禮滞乙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鉴嗤。我一直安慰自己斩启,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布醉锅。 她就那樣靜靜地躺著兔簇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硬耍。 梳的紋絲不亂的頭發(fā)上垄琐,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音经柴,去河邊找鬼狸窘。 笑死,一個胖子當(dāng)著我的面吹牛坯认,可吹牛的內(nèi)容都是我干的翻擒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼牛哺,長吁一口氣:“原來是場噩夢啊……” “哼陋气!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起引润,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤巩趁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淳附,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體议慰,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年奴曙,在試婚紗的時候發(fā)現(xiàn)自己被綠了褒脯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡缆毁,死狀恐怖番川,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脊框,我是刑警寧澤颁督,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站浇雹,受9級特大地震影響沉御,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昭灵,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一吠裆、第九天 我趴在偏房一處隱蔽的房頂上張望伐谈。 院中可真熱鬧,春花似錦试疙、人聲如沸诵棵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽履澳。三九已至,卻和暖如春怀跛,著一層夾襖步出監(jiān)牢的瞬間距贷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工吻谋, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留忠蝗,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓漓拾,卻偏偏與公主長得像什湘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晦攒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容