perlstyle - Perl 风格指南
当然,每个程序员都会有自己关于格式的偏好,但有一些通用的指南可以使你的程序更易于阅读、理解和维护。
最重要的是在所有代码中使用 strict 和 warnings,或者知道不使用它们的原因。你可以通过 no warnings
或 no strict
显式地关闭它们,并且可以将其限制为要禁用的特定警告或严格功能。-w 标志和 $^W
变量不应用于此目的,因为它们会影响你使用但没有编写的代码,例如来自核心或 CPAN 的模块。
一种简洁的安排方法是使用 use VERSION
语法,请求 5.36 或更高版本,这将启用 strict
和 warnings
编译指示(以及其他几个有用的 命名功能)。
use v5.36;
关于代码布局的美观性,Larry 唯一强烈关注的是,多行 BLOCK 的结束大括号应该与开始该结构的关键字对齐。除此之外,他还有其他不太强烈的偏好。
4 列缩进。
如果可能,将开括号放在与关键字相同的行上,否则对齐。
多行 BLOCK 的开括号之前留一个空格。
单行 BLOCK 可以放在一行上,包括大括号。
分号前不要加空格。
在“短”单行块中省略分号。
大多数运算符周围要有空格。
“复杂”下标(括号内)周围要有空格。
执行不同操作的代码块之间要有空行。
不要将 else 与 if 紧挨在一起。
函数名与其左括号之间不要加空格。
每个逗号后都要加空格。
长行在运算符(除 and
和 or
外)后换行。
与当前行匹配的最后一个右括号后要有空格。
将对应项垂直对齐。
只要不影响清晰度,就省略多余的标点符号。
Larry 对这些规则都有自己的理由,但他并不认为每个人的思维方式都和他一样。
以下是一些其他需要考虑的更重要的风格问题。
仅仅因为你 *可以* 以某种特定方式做某事,并不意味着你 *应该* 那样做。Perl 的设计允许你用多种方式做任何事,所以要考虑选择最易读的方式。例如
open(my $fh, '<', $foo) || die "Can't open $foo: $!";
比
die "Can't open $foo: $!" unless open(my $fh, '<', $foo);
更好,因为第二种方式将语句的主要内容隐藏在修饰符中。另一方面
print "Starting analysis\n" if $verbose;
比
$verbose && print "Starting analysis\n";
更好,因为主要内容不在于用户是否输入了 -v。
类似地,仅仅因为运算符允许你使用默认参数,并不意味着你必须使用默认参数。默认参数是为编写一次性程序的懒惰系统程序员准备的。如果你希望你的程序易读,请考虑提供参数。
同样,仅仅因为你 *可以* 在很多地方省略括号,并不意味着你应该这样做。
return print reverse sort num values %array;
return print(reverse(sort num (values(%array))));
有疑问时,请加括号。至少这样可以让某个可怜的家伙在 vi 中按 % 键。
即使你没有疑问,也要考虑维护你代码的人的心理健康,他们可能会在错误的地方加括号。
不要为了在循环的顶部或底部退出循环而进行愚蠢的扭曲,因为 Perl 提供了 last
运算符,你可以用它在循环的中间退出。只需稍微“缩进”它,使其更易见。
LINE:
for (;;) {
statements;
last LINE if $foo;
next LINE if /^#/;
statements;
}
不要害怕使用循环标签——它们的存在是为了提高可读性,以及允许多级循环中断。参见前面的示例。
避免在空上下文(即你只是丢弃它们的返回值)中使用 grep()
(或 map()
)或反引号。这些函数都有返回值,所以请使用它们。否则,请使用 foreach()
循环或 system()
函数。
为了可移植性,在使用可能并非在所有机器上都实现的功能时,请在 eval 中测试该结构以查看是否失败。如果您知道某个特定功能是在哪个版本或补丁级别实现的,您可以测试 $]
(在 English
中为 $PERL_VERSION
)以查看它是否可用。Config
模块还允许您查询在安装 Perl 时由 Configure 程序确定的值。
选择助记符标识符。如果您不记得助记符的含义,那么您就遇到了问题。
虽然像 $gotit
这样的短标识符可能没问题,但请使用下划线来分隔较长标识符中的单词。通常,$var_names_like_this
比 $VarNamesLikeThis
更易读,特别是对于非英语母语人士而言。这也是一个简单的规则,可以与 VAR_NAMES_LIKE_THIS
一致地使用。
包名有时是此规则的例外。Perl 非正式地将小写模块名称保留给像 integer
和 strict
这样的“pragma”模块。其他模块应该以大写字母开头并使用混合大小写,但可能不使用下划线,因为原始文件系统对模块名称的表示形式为文件,这些文件必须适合几个稀疏字节。
您可能会发现使用字母大小写来指示变量的作用域或性质很有帮助。例如
$ALL_CAPS_HERE constants only (beware clashes with perl vars!)
$Some_Caps_Here package-wide global/static
$no_caps_here function scope my() or local() variables
函数和方法名称似乎最适合使用全小写。例如,$obj->as_string()
。
您可以使用前导下划线来指示变量或函数不应在定义它的包之外使用。
如果您有一个非常复杂的正则表达式,请使用 /x
或 /xx
修饰符并在其中添加一些空格,使其看起来不那么像行噪声。当您的正则表达式包含斜杠或反斜杠时,请不要使用斜杠作为分隔符。
使用 and
和 or
运算符来避免过度使用括号来括住列表运算符,并减少像 &&
和 ||
这样的标点符号运算符的出现。像调用函数或列表运算符一样调用您的子例程,以避免过多的与号和括号。
使用 here 文档代替重复的 print()
语句。
将对应的东西垂直对齐,尤其是在它太长而无法在一行中显示的情况下。
$IDX = $ST_MTIME;
$IDX = $ST_ATIME if $opt_u;
$IDX = $ST_CTIME if $opt_c;
$IDX = $ST_SIZE if $opt_s;
mkdir $tmpdir, 0700 or die "can't mkdir $tmpdir: $!";
chdir($tmpdir) or die "can't chdir $tmpdir: $!";
mkdir 'tmp', 0777 or die "can't mkdir $tmpdir/tmp: $!";
始终检查系统调用的返回值。良好的错误消息应该发送到 STDERR
,包括导致问题的程序、失败的系统调用及其参数,以及(非常重要)应该包含导致错误的标准系统错误消息。这是一个简单但足够有效的示例
opendir(my $dh, $dir) or die "can't opendir $dir: $!";
在有意义的情况下,对你的音译进行排列
tr [abc]
[xyz];
考虑可重用性。为什么要浪费脑力在一个一次性任务上,而你可能想再次做类似的事情?考虑泛化你的代码。考虑编写一个模块或对象类。考虑让你的代码在use strict
和use warnings
生效的情况下干净地运行。考虑分享你的代码。考虑改变你的整个世界观。考虑...哦,算了。
尝试记录你的代码,并以一致的方式使用 Pod 格式。以下是常见的预期约定
使用C<>
表示函数、变量和模块名称(更一般地说,任何可以被认为是代码一部分的东西,比如文件句柄或特定值)。请注意,函数名称在名称后加上括号更易读,即function()
。
使用B<>
表示命令名称,例如cat或grep。
使用F<>
或C<>
表示文件名。F<>
应该是文件名唯一的 Pod 代码,但由于大多数 Pod 格式化程序将其呈现为斜体,因此 Unix 和 Windows 路径及其斜杠和反斜杠可能不太易读,最好使用C<>
呈现。
保持一致。
友善。