史上最糟糕的兩個變數名

4 贊 回覆發表於2015-04-20
譯者: 黃小非

| 2015-04-20 14:23   評論: 9 收藏: 6    

作為一個程式設計師,“起名字”是他們工作中非常重要的一部分。Phil Karlton就說過:“在電腦科學領域,有兩大難題,如何驗證快取和如何給各種東西命名。”雖然很難,但是每次在寫程式碼的時候,給事物起名字又是不可迴避的工作。無論是程式變數名還是資料庫表名或者是表裡的列名,甚至是檔案系統中的檔名,以及你的專案名稱、產品名稱,給這些東西起名字可不是個輕鬆活兒。

糟糕的命名方式隨處可見。你會發現,有的變數名字起得太短,根本沒法提供足夠的描述資訊。或許有這個問題的人都做過TRS-80 BASIC程式設計師,在這種BASIC語言裡,無論你起多長的變數名,只有名字的頭兩個字母有效,所以那個時候的程式設計師不得不在鍵盤邊兒上放個筆記本,以便將很短的變數名稱和他們的對應含義記錄下來,這樣才能不搞混淆。

有的時候,你會發現這樣的命名方法:直接將變數名稱中的原音字母省略,以此來縮短變數的長度。這種方法被用來替代常用的“截斷法”,也就是簡單地把字母截斷來縮短長度。比如你可以用$cstmr(原音省略)來代替$cust(直接截斷). 但是,對於customers(顧客)和costumers(服裝提供商)這兩個單詞來說,原音省略法就會造成混淆(customers和costumers採用原音省略法,其結果都是cstmr)。更糟糕的是,$cstmr缺乏原音字母,打字的時候會更加彆扭,而且從讀音的角度來說,也很難對其進行發音。

 

還有一種人為的特殊命名方式,有的時候程式的作者只是為了小幽一默,所以起了些有趣的名字。我就曾經見到過有人把迴圈變數命名為$crap (crap在英語裡是輕微的咒罵,跟damm,shit這種詞語差不多——譯者注),我的一個同事告訴我,他在給一段程式碼做整理的時候,看到過有個函式被命名為:THE_LONE_RANGER_RIDES_AGAIN()。雖然這樣的命名方式非常特殊,但是他們並不屬於我說的“糟糕”的命名的範疇。

雖然我很清楚,對於命名規範這種事情,大家是公說公有理,婆說婆有理,但是,我還是非常自信地宣佈,我認為,史上最糟糕的命名是:$data!

是的!必須是$data! 這個命名完全是迴圈定義,實際上就是一句廢話。就彷彿你把你們家所有的東西都扔到一個行李箱裡,然後在行李箱上面貼個條,赫然寫著:“東西”

正確變數命名應該寫清楚變數的資料型別。因此在命名是考慮資料型別是一個很好的提升命名質量的辦法。我有一次在看一段讀資料庫表記錄的程式碼時,看到了$data這個名字,大概像下面這樣:

$data = read_record();
print "ID = ", $data["CUSTOMER_ID"];

模糊的命名相當糟糕,糟糕程度緊隨其後的就是,長得幾乎一樣,無法分辨的變數名。因此,有史以來第二糟糕的變數名就是: $data2.如果這時候問問:“$data是什麼資料型別呢?”,然後你就很想給它換個名字了。把名字改成$record是一個好的開始。進一步改成$custormer_record,就更好一些了。

總的來說,任何僅僅依靠數字編號來區分的變數名都應該被重構。馬上舉個例子給你看,你就明白了:

$total = $price * $qty;
$total2 = $total - $discount;
$total2 += $total2 * $taxrate;
$total3 = $purchase_order_value + $available_credit;
if ( $total2 < $total3 ) {
    print "You can't afford this order.";
}

你可以發現,要讀懂這個程式碼就跟讀甲骨文一樣痛苦。很明顯,這個程式的目的就是要計算訂單的總花費,$total. 如果程式的邏輯沒有問題,那麼$total這個變數名也算是恰如其分。但是,偏偏有人修改了這個程式,給新增了計算折扣和稅率的功能,然後他還在變數命名上偷懶,直接起了個$total2, 更可恨的是,還有其他人在這個程式裡計算了使用者的可用賬戶金額,然後直接起名叫$total3!

真正倒黴催的是下面這行程式碼:

if ( $total2 < $total3 )

如果你看到了類似像$total2這樣的變數,那就應該把這個名字改得更加具體一些。花5分鐘的時間讓這些變數名稱變得更加合理。這個層面上的軟體重構是最簡單,代價最小,也是最安全的,尤其是在你要修改的變數是個區域性變數的時候。如果你不回頭看之前的程式碼,要想知道這句程式碼的意義是完全不可能的。所以你必須往回閱讀,看看哪個變數究竟是什麼意思。

讓我們用最簡單的“搜尋-替換”功能來解決我們之前發現的問題

$order_total = $price * $qty; 
$payable_total = $order_total - $discount;
$payable_total += $payable_total * $taxrate;
$available_funds = $purchase_order_value + $available_credit;
if ( $payable_total < $available_funds ) {
    print "You can't afford this order.";
}

經過修改後,唯一變化的就是變數名,而且程式碼變得簡單易懂了。現在對於每個_total,就不存在二義性的問題了。看看我們發現了什麼:原先if語句中的兩個比較變數的位置寫反了。有效的命名方法讓我們能夠更快地發現錯誤。

通常,我們都認為用數字作為變數的結尾是不好的命名方法,但是有一個例外。如果變數描述的實體本身就是以數字結尾的,那變數名最好也是以數字結尾。比如,如果我們要定義一個SHA-1雜湊實體,那乾脆就把它命名為$sha1,這樣就很好,你完全沒有必要把它搞成$sha_one,然後來避免在變數名中使用數字。

在我完成了對本文的第一版後,我創立了自己的命名規則,並使用Perl::Critic包來檢測上述提到的兩種命名問題。我製作的外掛 Perl::Critic::Bangs 可以檢測出這兩種問題:ProhibitVagueNames 和 ProhibitNumberNames.

還有哪些其他的糟糕的命名方法逼得你發瘋?你自己有去做些什麼糾正這些錯誤麼?

史上最糟糕的兩個變數名

相關文章