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
…后面必須接一個空格。if
和while
語句必須使用’{
‘和’}
’括起語句體艇潭,即使只有一行代碼拼窥。建議不使用單行的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ù)運算符, 賦值運算符等)的兩邊都要接空格,低級操作符(如:+-
)兩邊各有兩個空格睹逃,高級操作符(如:*%
)兩邊各有一個空格盗扇。盡量使用and
和or
而不要使用&&
和||
,請注意他們的區(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 = "ewords("[ +]", 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 goto
和else return
。
15筋栋、重復(fù)使用的炊汤、完成相對獨立功能的算法、代碼弊攘,應(yīng)該抽象為公共模塊抢腐。