一個名字如果需要註解來補充說明,它就已經失敗了。好名字要能自己回答三個問題:它為什麼存在?做什麼事?該怎麼被使用? 命名不是給實體貼代號,而是在讀者腦中畫出一幅關於它的清晰意象。
🧠 Why It Matters
- 名字是最先被讀到的抽象:Ousterhout 把名字視為一種抽象——它把複雜實體壓縮成一個能被快速理解的形式。好名字聚焦最重要的面向、略去次要細節。
- 描述問題領域,而非實作細節:名字該說「這是什麼(what)」,而不是「怎麼存的(how)」。用
employeeData而非inputRec、用printerReady而非bitFlag——讀者要的是意義,不是位元。 - 好名字同時說明「不是什麼」:只看到名字、不看宣告與文件的人,應該能相當接近地猜出它指什麼。若猜不出,換一個能畫出更清晰畫面的名字。
- 命名是投資最低、回報最高的可讀性手段:程式碼被讀的次數遠多於被寫的次數,把描述變數的那句話直接當成名字,往往就是最好的名字。
NOTE
Code Complete 的經驗法則:用一句話說明這個變數代表什麼,那句話本身通常就是最佳名稱。 numberOfPeopleOnTheUsOlympicTeam 太長、n 太短,numTeamMembers 剛剛好。
⚖️ Case Study
前 — 名字藏起了意圖
// 這段在做什麼?得逐行逆向推導
function getThem(theList) {
const list1 = [];
for (const x of theList) {
if (x[0] === 4) list1.push(x);
}
return list1;
}theList、x、list1、魔術數字 4 全都不透露意圖。讀者得先知道「這是一盤地雷遊戲的盤面、x[0] 是格子狀態、4 代表已標記」,才讀得懂——但這些知識程式碼一個字都沒說。
後 — 名字把領域知識寫進程式碼
const FLAGGED = 4;
const STATUS_VALUE = 0;
function getFlaggedCells(gameBoard) {
const flaggedCells = [];
for (const cell of gameBoard) {
if (cell[STATUS_VALUE] === FLAGGED) flaggedCells.push(cell);
}
return flaggedCells;
}程式碼一行都沒變複雜,卻突然可讀了:gameBoard、cell、FLAGGED 把原本只存在於作者腦中的意圖,直接寫進了名字。這正是命名作為抽象的價值——把意義從註解搬進識別字本身。
TIP
布林變數的名字應該是個述詞(predicate),讓讀者一眼知道 true 是什麼意思。cursorVisible 遠勝 blinkStatus——後者的 status 對布林太模糊,blink 又沒說什麼在 blink。
🔑 Takeaways
- 好名字自己回答「為什麼存在、做什麼、怎麼用」;需要註解解釋的名字就是失敗的名字。
- 名字是一種抽象:聚焦最重要的面向,描述問題領域而非實作細節。
- 「用一句話描述它」——那句話往往就是最好的名字。
- 布林命名用述詞,讓
true的語意寫在臉上。 - 把一段邏輯抽出來命名,是命名威力的延伸——見 Extract Function。
No notes yet — jot your takeaways or Q&A here.