🎯 什麼情境該想到我

分工:這張是語言無關的命名判準與流程。Go 特有的規則(套件名幫你省字、Getter 不加 Get、-er 介面、縮寫全大寫)→ 工具-Go命名慣例;把爛名字改好的重構步驟 → 神秘命名。

當你在替變數/函式/類別取名字,或看到一堆 d、tmp、data 看不懂時。

⚙️ 怎麼用

  1. 名字要能回答:它是什麼、為何存在、怎麼用。看到名字就不用再看註解。
  2. 用可讀、可搜尋的名字:elapsedTimeInDays 勝過 d;避免單字母(迴圈計數例外)。
  3. 別用誤導性名字、別加型別雜訊(匈牙利命名法過時)。
  4. 類別用名詞、函式用動詞;同一概念用同一個字(別 fetch/get/retrieve 混用)。

★ 名字長度 ∝ 使用處與宣告處的距離

這是最常被誤解的一條——「名字要有意義」不等於「名字要長」:

作用域讀者看到名字時,宣告在哪?合適的名字
3 行的迴圈就在上一行i、k, v、r(for _, r := range rows)
20 行的函式區域變數同一個螢幕total、buf、cfg
套件層級/匯出可能在另一個檔案、另一個 repoDefaultRetryPolicy、ErrQuotaExceeded

同一個概念在小範圍用長名字反而是雜訊:for index, currentRowValue := range rows 比 for i, r := range rows 難讀。所以命名問題有一半要靠 工具-縮小變數作用域 解決——作用域縮小了,短名字就合法了。

★ 命名的四步流程(卡住時照做)

  1. 先說出它是什麼:用一句完整的話描述它,「這是還沒被付款的訂單的數量」。
  2. 從句子裡挑名詞/動詞:unpaidOrderCount。
  3. 刪掉讀者從上下文就知道的字:在 package order 裡 → unpaidCount;在 func (s *Stats) 的方法裡已經很清楚 → 可能只要 unpaid。
  4. 說出來測試:唸給同事聽,對方能不能不看程式碼就猜到它是什麼?會不會跟另一個東西搞混?

第 1 步說不出來,就是設計問題而非命名問題——這個東西可能同時做了兩件事,或根本不該存在。

★ 一眼可認的壞名字

壞名字問題改法
data、info、item、obj什麼都是,等於什麼都沒說說它是什麼資料:invoice、quote
Manager、Helper、Util、Processor職責不明的收納箱,會一直長大拆開,各自用具體動作命名
flag、status 配 true/false讀呼叫端完全看不懂isRetryable、hasShipped
notDisabled、!isNotValid雙重否定一律用正向:isEnabled、isValid
timeoutMs int、sizeKB int單位靠名字記,會被搞錯用型別:Go time.Duration;TS 用 branded type 或物件 { ms: number }
同一概念 fetch/get/load/retrieve 混用讀者會以為它們行為不同全專案一個動詞對一個語義(例如 Get = 讀快取、Fetch = 走網路),寫進 工具-通用語言

★ 改名要靠工具,不要靠搜尋取代

  • Go:gopls 的 rename(編輯器 F2)以型別資訊找出所有引用,連跨套件、介面實作都會改;sed 會連字串和註解裡的同名字一起改爛。
  • TS:編輯器的 Rename Symbol 同理。
  • 匯出的名字改名 = 破壞 API。對外套件先加新名字、舊名字標 // Deprecated: use X. 再過一個版本刪。

🧪 我實際套用的紀錄

  • 2026-07-14:(待填)

⚠️ 注意

  • 想不到好名字,往往代表那段職責不清 → 該先釐清設計,命名是設計的鏡子。

  • 別為了「可搜尋」把所有名字都拉長:可搜尋性只對大作用域的名字有意義;區域變數沒人會全域搜尋。

  • 縮寫只用團隊公認的:ctx、req、cfg 大家都懂;calcAmtWTx 只有作者懂。

🔗 相關工具