好名字有兩個性質:精確一致

本節討論精確;下一節談一致。

最常見問題:太籠統#

最常見的命名問題是太籠統 / 太模糊——讀者搞不清楚指什麼,或誤以為它指其他東西(就像前面 block 的 bug)。

反例 1:getCount#

/** Returns the total number of indexlets this object is managing. */
int IndexletManager::getCount() { ... }

count 太籠統——數什麼?看到 getCount() 的呼叫,沒讀文件多半猜不出。

改善getActiveIndexletsnumIndexlets——讀者多半不需要看文件就能猜對。

反例 2:x、y 表示字元位置#

GUI 編輯器專案用 xy 表示字元在檔案中的位置:

  • 太籠統:可能也代表螢幕上的像素座標
  • 改善charIndexlineIndex——直接對應到程式碼實際實作的抽象

反例 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(在無回傳值的方法中)#

問題:

  • 誤導:暗示是回傳值
  • 沒說明它實際上裝什麼

改善:依其代表的內容命名,例如 mergedLinetotalChars

回傳值的方法中,result 是合理的:雖仍偏籠統,但讀者能理解「這個值最終會成為回傳值」。

紅旗:模糊名稱(Vague Name)#

變數或方法名廣泛到能指多種東西 → 它沒提供有用資訊,且實體更可能被誤用。

例外:短名也有合理用途#

for (i = 0; i < numLines; i++) { ... }

短迴圈中用 i 沒問題:

  • 變數的所有用途都看得到
  • 從程式碼就能推得它的意義

但若:

  • 迴圈長到看不下整段
  • 迭代變數的意義不直觀

→ 換成更具描述性的名稱。

也可能太「具體」#

void delete(Range selection) { ... }

selection 太具體,暗示「被刪的文字一定是 UI 中被選取的」。但這個方法可被用來刪任何範圍。改善range

命名的紅旗:難以為某物取名#

若你發現某變數很難取出精確、直覺、又不過長的名字 → 紅旗。

暗示這個變數可能沒有清楚的定義或用途

處理方式#

考慮替代的拆解(factoring):

  • 也許你想用一個變數同時代表多件事 → 拆成多個變數,每個就有更清楚的定義
  • 挑名字的過程能透過揭露弱點來改善設計

「難以命名」是設計問題的一個訊號——不是命名問題,是設計問題。