文档库 最新最全的文档下载
当前位置:文档库 › perl编码规范

perl编码规范

PERL编码规范

目录

目录

目录 ........................................................................................................................................................................ II 1文档介绍 .. (4)

1.1文档目的 (4)

1.2读者对象 (4)

1.3文档说明 (4)

2命名规则 (5)

2.1文件命名 (5)

2.2标识符 (5)

2.2.1变量 (5)

2.2.2包和类 (5)

2.2.3标识符缩写 (5)

2.2.4函数 (6)

2.3布尔类型 (6)

2.4数组和哈希 (7)

3注释 (8)

3.1文件头部注释 (8)

3.2文件中注释 (9)

3.3函数注释 (9)

3.4程序块注释 (9)

3.5语句注释 (10)

4代码布局 (11)

4.1括号 (11)

4.1.1方式一 (11)

4.1.2方式二 (11)

4.2关键字 (12)

4.3子程序和变量 (12)

4.4代码缩排 (13)

4.5代码块 (13)

4.6代码长度 (14)

4.7操作符 (14)

4.8语句结束符 (14)

4.9代码排列 (15)

4.10非末端表达式 (15)

4.11功能块顺序 (16)

5数值和表达式 (17)

5.1字符串界定符 (17)

5.2常量 (17)

5.3字符串 (17)

5.3.1两行 (17)

5.3.2多于两行 (17)

5.4哈希变量 (18)

6函数 (19)

6.1调用语法 (19)

6.2函数返回 (19)

7编程惯例 (20)

7.1使用USE STRICT (20)

7.2避免使用内部变量名称 (20)

7.3避免使用GOTO (20)

7.4语法检查(辅助工具) (21)

7.5使用标准模块 (21)

7.6其他 (21)

1 文档介绍

1.1 文档目的

本文档目的是制定一种好的PERL编码规范,使PERL软件开发人员,按照统一的编码风格编写程序,减少软件项目的成本,提高软件产品的健壮性,提高程序的运行效率,提高软件产品的可读性和易维护性。

1.2 读者对象

PERL语言开发人员。

1.3 文档说明

文档中红色标注的部分为规范的编码。

文档中蓝色标注的部分为不规范的编码。

作者:perlchina 明qq:492003149

2 命名规则

2.1 文件命名

文件名称统一用英文字母(大小写)、数字和下划线的组合,长度一般不超过20个字符,文件命名体现功能的含义,正式发布版本不能加入作者信息。Perl Scripts 文件的扩展名必须是".pl",Perl Module文件的扩展名必须是".pm"。

正确:

lucent_file_parser.pl

不是:

lucent_file.p

2.2 标识符

采用语法模板来定义标识符的名字,命名必须有一定的实际意义,由英文字母组成,中间可以根据语义的连续性,使用下划线连接。

2.2.1 变量

局部变量必须由小写字母和下划线组成,常量名必须由大写字母和下划线组成。由多个单词组成的名字里,使用下划线"_"把多个单词分开。全局变量以’g_’开头,其余部分的命名规则和局部变量相同。每个全局变量必须有注释说明其作用。

正确:

my $next_node;

不是:

my $node;

2.2.2 包和类

包、类的命名采用大小写混合、首字母大写的方法。

正确:

IO::Controller

2.2.3 标识符缩写

标识符缩写时要保留单词的开始字母,不是辅音字母的简写。

正确:

use List::Util qw( max );

DESC:

for my $desc (@orig_strs) {

my $len = length($desc);

next DESC if ($len > $UPPER_LIM);

$max_len = max($max_len, $len);

}

不是:

use List::Util qw( max );

DSCN:

for my $dscn (@rgnl_strgs) {

my $lngh = length $dscn;

next DSCN if $lngh > $UPPR_LMT;

$mx_lngh = max($mx_lngh, $lngh);

}

2.2.4 函数

由小写字母、下划线组成。

正确:

sub max

{

……

}

sub get_msc_name

{

……

}

不是:

sub getMscName

{

……

}

2.3 布尔类型

boolean类型的变量,或返回boolean类型的值的函数,在命名时要反映其属性,必须用is或者has开头。

正确:

sub is_valid;

sub is_metadata_available_for;

sub has_end_tag;

my $has_loading_finished;

my $has_found_bad_record;

# and later...

if (is_valid($next_record) && !$has_loading_finished) {

METADATA:

while (is_metadata_available_for($next_record)) {

push @metadata, get_metadata_for($next_record);

last METADATA if (has_end_tag($next_record));

}

}

else {

$has_found_bad_record = 1;

}

2.4 数组和哈希

数组类型的变量采用复数,hash类型的变量采用单数。要用undef显式释放变量空间。

正确:

my %option;

my %title_of;

my %count_for;

my %is_available;

# and later...

if ($option{'count_all'} && $title_of{$next_book} =~ m/$target/xms) {

$count_for{$next_book}++;

$is_available{$next_book} = 1;

}

my @events;

my @handlers;

my @unknowns;

# and later...

for my $event (@events) {

push @unknowns, grep { ! $_->handle($event) } @handlers;

}

print map { $_->err_msg } @unknowns;

3 注释

所有注释可用英文或中文书写,尽量使用英文注释。保持注释和代码的完全一致,修改程序时,必须修改相应的注释。注释的行数一般应在程序总行数的1/5到1/3。禁止出现错别字。注释应该语义明确,避免出现二义性。

3.1 文件头部注释

每个含有源代码的文件必须在文件开始有关于该文件的介绍性注释。其中列出文件名、创建者、创建日期、功能描述、版本信息、版权声明;如果对文件进行了修改,应该在文件头中说明修改人、修改日期、修改原因,并变更文件的版本信息,最新版本信息放到最前面。

格式为:

#*********************************************************

# FileName: lucent_file_parser.pl

# Creator: Phonix

# 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

#*********************************************************

不是简单的:

#========================================

#Created By:Phonix

#Created Time: 2006-01-09

#Modified Time: 2006-01-17

#========================================

3.2 文件中注释

建议在文件中标识出修改部分的起止位置。

正确:

# add mysql&oracle db support begin

……

# add mysql&oracle db support end

3.3 函数注释

在每个函数前必须写描述性注释。说明这个函数的功能、参数和函数的返回值。

格式为:

#*******************************************************************

# 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'

#*********************************************************************

不是简单的:

##########################################

#function name : get_ldap

#desc : get config info from ldap server

##########################################

3.4 程序块注释

程序块注释用于说明程序中的关键算法、使用某种技巧的代码以及修改、测试、阅读时必须加以注意的代码。

格式为:

#*********************************************************************

#注释内容

#......

#......

#********************************************************************

3.5 语句注释

用于对特定程序语句进行说明,建议采取在语句行末尾说明的方法,同时注释换行后也要对齐。格式为:

my @names = (

'Damian', # Primary key

# the key is

'Matthew', # Disambiguator

'Conway', # General class or category

);

4 代码布局

4.1 括号

建议括号、插入语可以采用两种方式之一,但是在一个程序里选定那种方式之后,那么要至始至终保持一致。

4.1.1 方式一

采用K&R风格。

格式为:

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";

}

}

4.1.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";

}

}

4.2 关键字

把关键字和其他的内容分开,关键字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++;

}

不是:

for(@results){

print_sep( );

print;

}

while($min < $max){

my $try = ($max - $min) / 2;

if($value[$try] < $target) {

$max = $try;

}

else{

$min = $try;

}

}

if($condition) {$i++;}

4.3 子程序和变量

不要把子程序或变量和其后的括号部分分开。

正确:

my @candidates = get_candidates($marker);

CANDIDATE:

for my $i (0..$#candidates) {

next CANDIDATE if open_region($i);

$candidates[$i]

= $incumbent{ $candidates[$i]{region} };

}

不是:

my @candidates = get_candidates ($marker);

CANDIDATE:

for my $i (0..$#candidates) {

next CANDIDATE if open_region ($i);

$candidates [$i]

= $incumbent {$candidates [$i] {region}};

}

4.4 代码缩排

缩进采用四个空格,或一个TAB(1 TAB 设置成四个空格)。

4.5 代码块

不要把两句话放在一行,每行只能写一个语句。

正确:

while (my $record = <$inventory_file>) {

chomp $record;

next RECORD if $record eq $EMPTY_STR;

my @fields = split $FIELD_SEPARATOR, $record;

update_sales(\@fields);

$count++;

}

不是:

while (my $record = <$inventory_file>) {

chomp $record; next RECORD if $record eq $EMPTY_STR;

my @fields = split $FIELD_SEPARATOR, $record; update_sales(\@fields);$count++;

}

4.6 代码长度

每个函数体的语句行不能超过100行(不包括注释,一个分号算一行)。每行长度不要超过78个字符,超过该长度时,必须考虑换行,从低优先级的操作符处分割长表达式, 在赋值符前断开长的语句。

正确:

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;

4.7 操作符

二元运算符(算术运算符, 赋值运算符等)的两边都要接空格,低级操作符(如:+-)两边各有两个空格,高级操作符(如:*%)两边各有一个空格。

在运算符'->'两边不要使用空格,在一元操作符和操作数两边不要使用空格。

可以使用括号来表示运算的先后顺序。

正确:

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);

4.8 语句结束符

在每个语句后边要填加分号。

正确:

while (my $line = <>) {

chomp $line;

if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {

push @comments, $2;

}

print $line;

}

4.9 代码排列

数组或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},

);

4.10 非末端表达式

采用中间变量代替长表达式。

正确:

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);

4.11 功能块顺序

在每个Perl Scripts中,每个功能块之间必须有一个空行。主程序为main()函数,功能块出现顺序如下:use modules;

global variable 定义

main定义

sub routine 定义

5 数值和表达式

5.1 字符串界定符

需要用变量替换的字符串用双引号,否则用单引号。

正确:

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';

5.2 常量

使用字符常量,而不要直接用数值。

正确:

use Readonly;

Readonly my $MOL YBDENUM_ATOMIC_NUMBER => 42;

# and later...

print $count * $MOL YBDENUM_ATOMIC_NUMBER;

不是:

print $count * 42;

5.3 字符串

5.3.1 两行

对于两行的字符串,要用“.”进行连接。

正确:

$usage = "Usage: $0 [-full]\n"

. "(Use -full option for full dump)\n";

不是:

$usage = "Usage: $0 [-full]

(Use -full option for full dump)";

5.3.2 多于两行

对于多于两行,要采用如下格式:

正确:

$usage = <<"END_USAGE";

Usage: $0 [-full] [-o] [-beans]

Options:

-full : produce a full dump

-o : dump in octal

-beans : source is Java

END_USAGE

不是:

$usage = "Usage: $0 [-full] [-o] [-beans]\n"

. "Options:\n"

. " -full : produce a full dump\n"

. " -o : dump in octal\n"

. " -beans : source is Java\n"

;

5.4 哈希变量

Hash变量的定义采用双箭头(=>)方式。

正确:

%default_service_record = (

name => '',

rank => 'Recruit',

serial => undef,

unit => ['Training platoon'],

duty => ['Basic training'],

);

不是:

%default_service_record = (

'name', '',

'rank', 'Recruit',

'serial', undef,

'unit', ['Training platoon'],

'duty', ['Basic training'],

);

6 函数

6.1 调用语法

调用时要使用圆括号,不管是否有参数。

正确:

fix();

coerce($input, $INTEGER, $ROUND_ZERO);

不是:

fix;

6.2 函数返回

在函数中要进行显式的return返回。

正确:

sub set_terseness {

my ($terseness) = @_;

my $default_terseness = $terseness;

return; # Explicitly return nothing meaningful }

不是:

sub set_terseness {

my ($terseness) = @_;

my $default_terseness = $terseness;

}

7 编程惯例

7.1 使用use strict

所有Perl Scripts 文件中必须在开始使用“use strict;”,进行严格的语法检查,便于查找错误。

7.2 避免使用内部变量名称

避免使用Perl内部变量。使用“use English;”装入Perl内部变量的符号名称。使用my来限定变量的作用域。下面是一些Perl内部变量名称的对应关系。

$_ $ARG

@_ @ARG

$! $ERRNO

$? $CHILD_ERROR

$$ $PID

$0 $PROGRAM_NAME

$. $INPUT_LINE_NUMBER

$| $OUTPUT_AUTOFLUSH

$@ $EVEL_ERROR

$& $MATCH

$` $PREMATCH

$' $POSTMA TCH

$+ $LAST_PAREN_MATCH

$/ $RS

$\ $ORS

$< $UID

$> $EUID

$( $GID

$) $EGID

$] $PERL_VERSION

$? $CHILD_ERROR

7.3 避免使用goto

避免使用goto语句(只有在从多重循环的内部跳出时才可以使用)。除非能够特别有效的增加程序的效率并且不影响程序良好结构的特殊情况。

相关文档