好名字有兩個性質:精確與一致。
本節討論精確;下一節談一致。
最常見問題:太籠統#
最常見的命名問題是太籠統 / 太模糊——讀者搞不清楚指什麼,或誤以為它指其他東西(就像前面 block 的 bug)。
反例 1:getCount#
/** Returns the total number of indexlets this object is managing. */
int IndexletManager::getCount() { ... }count 太籠統——數什麼?看到 getCount() 的呼叫,沒讀文件多半猜不出。
改善:getActiveIndexlets 或 numIndexlets——讀者多半不需要看文件就能猜對。
反例 2:x、y 表示字元位置#
GUI 編輯器專案用 x、y 表示字元在檔案中的位置:
- 太籠統:可能也代表螢幕上的像素座標
- 改善:
charIndex、lineIndex——直接對應到程式碼實際實作的抽象
反例 3:blinkStatus#
// Blink state: true when cursor visible.
private boolean blinkStatus = true;問題:
status對 boolean 太模糊(true / false 各代表什麼?)blink也模糊(什麼在 blink?)
改善:
// Controls cursor blinking: true means the cursor is visible,
// false means the cursor is not displayed.
private boolean cursorVisible = true;boolean 變數的名字應該是個述詞(predicate)——讓讀者直接知道 true 是什麼意思。
反例 4:哨兵值#
private static final String VOTED_FOR_SENTINEL_VALUE = "null";只說明它是哨兵,不說它的特殊意義。改善:NOT_YET_VOTED。
反例 5:result(在無回傳值的方法中)#
問題:
- 誤導:暗示是回傳值
- 沒說明它實際上裝什麼
改善:依其代表的內容命名,例如 mergedLine、totalChars。
在有回傳值的方法中,
result是合理的:雖仍偏籠統,但讀者能理解「這個值最終會成為回傳值」。
紅旗:模糊名稱(Vague Name)#
變數或方法名廣泛到能指多種東西 → 它沒提供有用資訊,且實體更可能被誤用。
例外:短名也有合理用途#
for (i = 0; i < numLines; i++) { ... }短迴圈中用 i 沒問題:
- 變數的所有用途都看得到
- 從程式碼就能推得它的意義
但若:
- 迴圈長到看不下整段
- 迭代變數的意義不直觀
→ 換成更具描述性的名稱。
也可能太「具體」#
void delete(Range selection) { ... }selection 太具體,暗示「被刪的文字一定是 UI 中被選取的」。但這個方法可被用來刪任何範圍。改善:range。
命名的紅旗:難以為某物取名#
若你發現某變數很難取出精確、直覺、又不過長的名字 → 紅旗。
暗示這個變數可能沒有清楚的定義或用途。
處理方式#
考慮替代的拆解(factoring):
- 也許你想用一個變數同時代表多件事 → 拆成多個變數,每個就有更清楚的定義
- 挑名字的過程能透過揭露弱點來改善設計
「難以命名」是設計問題的一個訊號——不是命名問題,是設計問題。