好的變數名稱是程式可讀性的關鍵要素。名稱既不是隨意取的暱稱,也不是越短越好的縮寫——它應該精確地描述變數所代表的實體。本章涵蓋命名的一般原則、特定資料型別的命名、命名慣例、縮寫策略,以及應避免的命名陷阱。

11.1 選擇好名稱的考量#

最重要的原則#

名稱應該完整且精確地描述變數所代表的實體。最好的技巧是用文字說明變數代表什麼,而那句話本身往往就是最佳的名稱。

  • numberOfPeopleOnTheUsOlympicTeam — 可讀但太長
  • n, np — 太短,毫無意義
  • numTeamMembers, teamMemberCount — 剛剛好

名稱應該傾向描述問題領域(what)而非實作細節(how)。例如用 employeeData 而非 inputRec,用 printerReady 而非 bitFlag

最佳名稱長度#

研究顯示,變數名稱平均 10 到 16 個字元時,除錯所需的心力最低。8 到 20 個字元的範圍也不錯。太短的名稱(如 x)無法傳達足夠資訊,太長的名稱則會模糊程式的視覺結構。

作用域對名稱的影響#

  • 短名稱(如 i):適合用於作用域極小的區域變數或迴圈變數,暗示該變數沒有超出幾行程式碼的意義。
  • 長名稱:適合用於全域變數或不常使用的變數。
  • 全域命名空間中的變數應考慮加上子系統前綴(如 g_RunningTotal),或使用 namespace / package 來避免衝突。

計算值限定詞#

當變數包含計算值(如 Total、Sum、Average、Max、Min)時,將限定詞放在名稱末尾

  • revenueTotal, expenseAverage — 一致且對稱
  • 避免混用 totalRevenuerevenueTotal

Num 的歧義:放在開頭(numCustomers)表示總數,放在末尾(customerNum)表示索引。建議改用 Count / Total 表示總數,Index 表示索引,避免混淆。

常見對稱詞組#

命名中使用對稱詞組能提升一致性和可讀性:

  • begin / endfirst / lastmin / max
  • next / previousold / newopen / close
  • source / targetsource / destination
  • visible / invisiblelocked / unlockedup / down

11.2 為特定型別的資料命名#

迴圈索引(Loop Indexes)#

  • 簡單迴圈可使用 ijk,但如果迴圈超過幾行或有巢狀結構,應使用有意義的名稱。
  • 巢狀迴圈中,score[teamIndex][eventIndex] 遠比 score[i][j] 清晰,也能避免索引交叉錯誤(index cross-talk)。
  • 若變數在迴圈結束後仍會使用,必須給予描述性名稱(如 recordCount)。

狀態變數(Status Variables)#

  • 不要用 flag 作為名稱——它不傳達任何意義。
  • 用具體的描述取代:dataReadyreportTyperecalcNeeded
  • 搭配列舉型別或具名常數來設定和測試值,例如 reportType == ReportType_Annual,而非 printFlag == 16

暫存變數(Temporary Variables)#

  • tempx 等名稱通常代表程式設計師尚未充分理解問題。
  • 應替換為有意義的名稱,例如將二次方程式中的 temp 改為 discriminant

布林變數(Boolean Variables)#

常見的好名稱包括:

名稱語意
done某件事是否已完成
error是否發生錯誤
found是否已找到目標值
success / ok操作是否成功(可用更具體的名稱如 processingComplete
  • 布林名稱應暗示 true/false 的語意——status 是差勁的布林名稱,statusOK 才好。
  • 使用正面語意的名稱:foundnotFound 好,因為 if not notFound 難以閱讀。
  • 有些程式設計師喜歡加上 is 前綴(如 isDoneisFound),好處是讓模糊的名稱無所遁形(isStatus? 顯然不合理)。

列舉型別(Enumerated Types)#

  • 為成員加上群組前綴,例如 Color_RedColor_BluePlanet_Earth
  • 若語言會自動以型別名稱作為前綴(如 Color.Red),則不需重複。

具名常數(Named Constants)#

  • 命名應描述常數代表的抽象實體,而非它的值。
  • CYCLES_NEEDED 是好名稱,FIVE 是壞名稱——因為 FIVE = 6.0 就顯得荒謬了。

11.3 命名慣例的力量#

命名慣例(Naming Conventions)帶來的好處不在於選擇了哪套規則,而在於有規則存在這個事實本身:

  • 減少局部決策的負擔,讓注意力集中在更重要的事物上
  • 在專案間轉移知識,加速學習新程式碼
  • 避免同一概念出現多個名稱(如 pointTotaltotalPoints 並存)
  • 彌補語言本身的弱點(如模擬具名常數或區分變數作用域)
  • 強調相關變數之間的關係

適合建立命名慣例的時機:多人協作、程式碼會被維護或審查、專案規模大到無法全部記在腦中、或有大量領域特定術語需要標準化。

11.4 非正式命名慣例#

語言無關的通用指引#

  • 變數和物件以小寫字母開頭(variableName),函式以大寫字母開頭(RoutineName())。
  • 區分類別與物件:可透過首字母大小寫、前綴(t_a_)、或給物件更具體的名稱(employeeWidget)。
  • 全域變數:加 g_ 前綴。
  • 成員變數:加 m_ 前綴。
  • 具名常數:使用 ALL_CAPS
  • 列舉成員:以型別名稱作前綴(Color_Red)。
  • 增強可讀性:使用 camelCase 或 underscore_case 來分隔單字,但不要在同一專案中混用。

各語言的慣例#

點擊展開:各主要語言的命名慣例

C 語言

  • c/ch 表示字元、i/j 表示整數索引、n 表示數量、p 表示指標、s 表示字串
  • 巨集用 ALL_CAPS,變數和函式用 all_lowercase,以底線分隔

C++

  • i/j 表示整數索引、p 表示指標
  • 常數、typedef、巨集用 ALL_CAPS
  • 類別用 MixedUpperAndLowerCase,變數和函式用 camelCase

Java

  • 常數用 ALL_CAPS,以底線分隔
  • 類別和介面用 ClassOrInterfaceName
  • 變數和方法用 variableOrMethodName
  • 存取器使用 get/set 前綴

11.5 標準化前綴#

標準化前綴(如匈牙利命名法 Hungarian Notation)由兩部分組成:

  1. 使用者定義型別縮寫(UDT):描述資料型別,如 wn(視窗)、scr(螢幕區域)、doc(文件)、pa(段落)。
  2. 語意前綴(Semantic Prefix):描述變數的用途,如 c(計數)、i(索引)、first/last(陣列的首尾元素)、min/max(絕對邊界)、g(全域)、m(成員)、p(指標)。

例如:firstPaActiveDocument(活動文件的第一個段落)、cPa(段落數量)、iPa(段落索引)。

標準化前綴的好處是讓名稱更精練且一致,但主要陷阱是程式設計師可能因前綴已夠明確而省略有意義的描述性名稱。iPa 雖明確,但 ipaActiveDocument 可讀性更好。

11.6 建立具備可讀性的短名稱#

現代語言幾乎沒有變數名稱長度的限制,因此很少需要刻意縮寫。若確有需要,以下是幾種策略:

點擊展開:縮寫策略一覽
  • 使用字典中的標準縮寫
  • 移除非首位的母音(computer -> cmptrscreen -> scrn
  • 移除冠詞(and、or、the)
  • 使用每個單字的前幾個字母
  • 在每個單字的第一、二或三個字母後截斷
  • 保留每個單字的首尾字母
  • 最多使用三個重要單字
  • 移除無用的後綴(-ing、-ed)
  • 保留每個音節中最顯著的發音

縮寫的注意事項#

  • 不要只省一個字元——打一個字幾乎不費力,但可讀性的損失不值得。
  • 保持一致——對同一單字始終使用相同縮寫(如全部用 Num 或全部用 No,不要混用)。
  • 名稱必須能唸出來——用 xPos 而非 xPstn;通過「電話測試」,即能口述程式碼給他人。
  • 避免造成誤讀——ENDBBEND 好。
  • 用同義詞解決碰撞——若 firedfull revenue disbursal 都縮寫為 frd,可改用 dismissedcomplete revenue disbursal
  • 在專案層級維護標準縮寫文件——納入版本控制,按完整單字排序,避免重複縮寫。

程式碼被閱讀的次數遠多於被撰寫的次數。縮寫策略應該優先考慮閱讀時的便利性,而非撰寫時的方便。

11.7 應該避免的名稱#

應避免的類型說明與範例
誤導性名稱確保名稱無歧義,例如 FALSE 不應作為 “Fig and Almond Season” 的縮寫
語意相似的名稱inputinputValue 可以互換而不影響程式,代表兩者都需重新命名
外觀相似的名稱clientRecsclientReps 只差一個字母,容易混淆。至少要有兩個字母的差異
發音相似的名稱wraprap 在口頭討論時無法區分
帶數字的名稱file1file2 幾乎總是可以用更好的方式區分。若數字有意義,考慮使用陣列
刻意拼錯的名稱hilite 還是 hilight?沒人記得住「正確的」錯誤拼法
僅靠大小寫區分frdFRDFrd 代表不同變數是合法的,但完全是武斷且令人困惑的
多種自然語言混用跨國專案應統一使用單一自然語言;英語變體也需統一(color vs colour
與標準型別或保留字衝突-
與變數內容完全無關margaretpookie 不應出現在程式碼中
難以辨認的字元注意 1/l/I0/O2/ZS/5G/6 等容易混淆的配對

要點#

  • 好的變數名稱是程式可讀性的關鍵,應盡可能具體,避免通用到可用於多種用途。
  • 迴圈索引、狀態變數、布林變數、列舉型別、具名常數等,各有各的命名考量。
  • 命名慣例的價值在於有慣例存在本身,它能區分區域、類別與全域資料,區分型別、常數、列舉與變數。
  • 現代語言中很少需要縮寫;若必須縮寫,應在專案層級記錄並保持一致。
  • 程式碼被閱讀的次數遠多於被撰寫的次數,命名應優先考慮閱讀者的便利。