有意義的命名

有意義的命名 (Meaningful Names) #

核心觀點 #

在軟體開發中,命名(Naming)不僅僅是給變數代號,它深刻影響程式碼的可讀性(Readability)與可維護性(Maintainability)。

一個好名稱應能清晰表達該變數、函式或類別的內容目的
好命名能讓閱讀程式碼的人像讀文章一樣順暢;而糟糕命名則會製造理解障礙,甚至引發誤解。

程式碼主要是寫給「人」看的,其次才是給機器執行。選擇好名稱的關鍵,在於具備優良的描述技巧與建立團隊共通的文化背景。


命名的基本原則 #

1. 讓名稱代表意圖 (Use Intention-Revealing Names) #

名稱如果需要註解補充說明,就代表它已經失敗。名稱本身就該回答:它為什麼存在?做什麼事?怎麼被使用?

# Bad Naming: 需要去推測 d 是什麼
def d(s):
    ...


# Good Naming: 直接看出是根據速度計算距離
def calculate_distance(speed):
    ...

2. 避免誤導 (Avoid Disinformation) #

程式設計師應避免留下掩蓋程式碼本意的錯誤線索。

  • 避免用專有名詞作為變數名: 如 hp, aix, sco,除非真的與該平台有關,否則容易混淆
  • 小心使用資料結構關鍵字: 除非該變數真的是 List,否則別用 accountList
    (改用 accountsaccountGroup ),以免誤導開發者以為它是特定型別。
  • 避免過於相似的名稱: 如 ProductInfoProductData,這兩者語意上幾乎沒差,讀者無法區分具體用途。

無效資訊的陷阱:用 a1, a2, ... aN 這種數列命名法完全無法提供任何有意義的線索。
此外,若變數 Name 已足夠清晰,就不需改成 NameString,除非需要特別強調它是浮點數或其他非直覺型別。


考量人類的認知習慣 #

1. 名稱應易於朗誦 (Pronounceable Names) #

寫程式是項社交活動。如果變數名稱唸不出來,在 Code Review 或討論時就會非常尷尬且難以溝通。

# Bad Naming: 像是密碼,難以在口頭討論中提及
def calc_avg_grd(s_grds):
    ...


# Good Naming: 清晰、像自然的語句
def calculate_average_grade(student_grades):
    ...

2. 名稱應易於搜尋 (Searchable Names) #

單一字母的變數名稱(如 e)或魔術數字(Magic Numbers),在大型專案中極難被精確搜尋定位。

  • 長度與視野成正比:變數的有效範圍(Scope)越大,名稱就應越長、越具描述性

  • 取代魔術數字:

    # Bad: 數字 7 的意義不明,且很難搜尋(文中太多 7)
    if count % 7: ...
    
    # Good: 定義常數,易於修改且語意清晰
    MAX_CLASSES_PER_STUDENT = 7
    if count % MAX_CLASSES_PER_STUDENT: ...
    

減少雜訊與思維轉換 #

1. 減少多餘資訊 #

  • 不要把型別編碼進名稱:在強型別或現代 IDE 環境下,不需把型別資訊(如 i_count, strName)寫在變數名中
  • 成員變數字首是廢話: 現代類別設計中,不需在成員變數前加 m_ ,這往往會被大腦自動忽略
  • 介面與實作的區分: 如果須區分 Interface 和 Implementation,請修飾「實作」(例如 ShapeFactoryImp), 而不是在介面上加前綴(避免用 IShapeFactory)。

2. 避免思維轉換 (Map to Mental Models) #

讀者不該在閱讀時還需在腦中將你的變數「翻譯」成他們熟知概念。請選擇對方熟悉的術語:

  • 針對程式設計師(Solution Domain): 如果讀者是工程師,用電腦科學術語,例如 AccountQueue, MacAddressFactory
  • 針對領域專家(Problem Domain): 如果程式碼涉及特定業務邏輯,請使用該領域的專業術語
範例:解決方案領域 vs 問題領域

情境:購物車設計

  • Solution Domain (給工程師看): 強調資料結構

    class Cart:
        def __init__(self):
            self.data = []  # 泛用的資料容器
    
        def insert(self, product):
            self.data.append(product)
    
  • Problem Domain (給業務邏輯看): 強調業務意義

    class Cart:
        def __init__(self):
            self.products = []  # 明確指出是商品
    
        def add_product(self, product):
            self.products.append(product)
    

結構與語法的一致性 #

1. 概念一致性 (Pick One Word per Concept) #

不要讓 controllermanagerdriver 同時混雜在專案中代表類似概念。 這會讓人困惑 DeviceManagerProtocolController 到底有什麼本質差別。請選定一個詞,然後貫徹到底。

2. 詞性選擇 #

  • 類別 (Class) / 物件 (Object):應用名詞或名詞片語
  • 方法 (Method):應用動詞或動詞片語

3. 上下文的拿捏 (Context) #

添加有意義的上下文: 變數名若過於簡單,可放入適當函式或類別中賦予意義,或透過命名補充。

# 修正前:CarInfo 類別內的變數重複 car_ 字首
class CarInfo:
    def get_car_speed(self):
        return self.car_speed


# 修正後:移除贅字,因為 reader 已經知道這是 Car 的方法
class Car:
    def get_speed(self):
        return self.speed