perlstyle - Perl 樣式指南
每個程式設計師當然都會有自己偏好的格式,但有一些通則可以讓你的程式更容易閱讀、理解和維護。
最重要的,是在你所有的程式碼中使用 strict 和 warnings,或知道為什麼不使用它們。你可以透過 no warnings
或 no strict
明確關閉它們的特定部分程式碼,而且可以限制在你想停用的特定警告或 strict 功能。-w 旗標和 $^W
變數不應該用於此目的,因為它們會影響你使用的程式碼,但沒有寫入,例如核心或 CPAN 的模組。
一個簡潔的方法是使用 use VERSION
語法,要求 5.36 或以上的版本,這將啟用 strict
和 warnings
實用程式(以及其他幾個有用的 命名功能)。
use v5.36;
關於程式碼配置的美學,Larry 唯一強烈關心的是多行區塊的閉合大括號應該與開始結構的關鍵字對齊。除此之外,他還有其他不太強烈的偏好
4 欄位縮排。
如果可能,將開頭大括號放在與關鍵字同一行,否則對齊。
多行區塊的開頭大括號前面有空格。
單行區塊可以放在一行,包括大括號。
分號前面沒有空格。
「短」單行區塊中省略分號。
運算子周圍的空格。
「複雜」下標周圍的空格(在括號內)。
執行不同功能的區塊之間的空白行。
不緊貼的 else。
函式名稱與其開頭括號之間沒有空格。
每個逗號後面的空格。
長行在運算子後斷行(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
)以查看它是否會存在。當安裝 Perl 時,Config
模組也會讓你詢問由 Configure 程式決定的值。
選擇助記符識別碼。如果你記不住助記符是什麼意思,你就有問題了。
雖然像 $gotit
這樣的短識別碼可能沒問題,但請使用底線來分隔較長識別碼中的字詞。通常較容易閱讀 $var_names_like_this
而不是 $VarNamesLikeThis
,特別是非英語母語人士。這也是一個簡單的規則,與 VAR_NAMES_LIKE_THIS
一致運作。
套件名稱有時是此規則的例外。Perl 非正式地保留小寫模組名稱給「實用」模組,例如 integer
和 strict
。其他模組應以大寫字母開頭並使用混合大小寫,但由於原始檔案系統將模組名稱表示為必須放入幾個稀疏位元的檔案的限制,因此可能不使用底線。
你可能會發現使用字母大小寫來表示變數的範圍或性質很有幫助。例如
$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
運算子來避免必須對清單運算子加上太多括號,並減少 &&
和 ||
等標點符號運算子的發生率。呼叫你的子常式,就像它們是函式或清單運算子一樣,以避免過多的縮寫符號和括號。
使用這裡文件,而不是重複的 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()
。
對命令名稱(例如 cat 或 grep)使用 B<>
。
對檔案名稱使用 F<>
或 C<>
。F<>
應該是檔案名稱唯一的 Pod 程式碼,但由於大多數 Pod 格式化程式會將其呈現為斜體,因此具有斜線和反斜線的 Unix 和 Windows 路徑可能可讀性較差,並使用 C<>
呈現會比較好。
保持一致性。
保持友善。