你的命名必須準確傳達意圖,不能讓人猜
程式碼是寫給人看的,不是給機器看的。
如果需要花時間去猜一個變數或函式在做什麼,那這個程式碼已經發臭了。
好的程式碼不應該有任何「猜測」的空間。
你寫的程式碼,最後會由人來維護,這個人可能是未來的你,也可能是你的同事,或是其他陌生人。
如果他們看不懂,每一次的維護都會變成一場災難。
怎麼樣讓程式碼有可讀性?
也就是從 好命名 開始,有好命名,命就好。
命名不只是換個變數名,它關乎你對資料結構的理解,你不需要再維護程式碼旁邊的註解,只要專注好你的功能本身就好。
資料結構優先:寫程式前,先釐清你處理的資料結構是什麼。
一個儲存訂單項目的陣列,命名為 orderItems
,會比 o
、d
或 list
更具體。
用動詞或動詞片語命名函式:函式代表行為,它的名稱必須明確指出它的作用。
getUserById(userId)
validateUserInput(userData)
布林變數使用 is/has/can/should
:這讓變數的布林性質一看就懂。
isUserLoggedIn
hasValidEmail
避免縮寫和簡寫:不要為了省幾個字而讓未來的自己和同事陷入「通靈遊戲」。使用 currentUser
而非 usr
,userPassword
而非 pwd
。
使用領域語言:命名應與你解決的業務問題緊扣。
class OrderProcessor
優於 class DataProcessor
processOrder(order)
優於 processData(input)
看看下面這段程式碼:
// 🔴 飄散臭味
function p(d) {
let r = [];
for (let i = 0; i < d.length; i++) {
let item = d[i];
if (item.s > 0) {
let t = item.p * item.q;
r.push({
id: item.id,
name: item.n,
total: t
});
}
}
return r;
}
這個函式有三個問題:
神奇的單字元變數:p
, d
, r
, s
, t
… 誰知道這些是什麼?
魔術數字:item.s > 0
,這個 0
代表什麼意思?
不必要的縮排和複雜性:這個函式可以寫得更簡單。
在我們動手改變數名之前,首先思考一個問題:d
是什麼?p
函式在做什麼?
首先搞懂了資料結構(d
是 orderItems
)和函式的意圖(p
是 calculateEffectiveOrderTotals
。
p 函式看起來像是在處理一個「訂單項目清單」(d),item
的 s
應該是某種狀態,p
是價格,q
是數量。
再來計算每個有效(item.s > 0)項目的總價,最後回傳一個新的清單。
重構命名後的程式碼長這樣:
// 更清楚地表達了意圖:計算可用訂單項目的總價
const ITEM_STATUS_AVAILABLE = 1;
function calculateAvailableItemsTotals(orderItems) {
const processedItems = [];
for (let i = 0; i < orderItems.length; i++) {
const item = orderItems[i];
if (item.status === ITEM_STATUS_AVAILABLE) {
const itemTotal = item.price * item.quantity;
processedItems.push({
id: item.id,
name: item.name,
total: itemTotal,
});
}
}
return processedItems;
}
命名的影響:猜測 vs 理解
好命名可以讓你用最簡單、最直接的方式,設計出合格60分的程式碼,但這樣子還不夠。
如果程式碼需要超過三層縮排,代表還是有優化空間。
終極優化版本:
// 🟢 更簡單、更可讀性
function calculateAvailableItemsTotals(orderItems) {
return orderItems
.filter(item => item.status === ITEM_STATUS_AVAILABLE)
.map(item => ({
id: item.id,
name: item.name,
total: item.price * item.quantity,
}));
}
程式設計的思路應該是操作資料流,而不是手動去遍歷然後判斷。
先過濾,再轉換。 消除那個 if
。
它清楚地告訴下一個人:
我們先篩選出可用的項目,然後把它們轉換成我們想要的格式,一行解決更清晰。
這才是「乾淨的程式碼」。
在命名時,問自己:
我們之後的系列文章將以 JavaScript 為主,帶你持續精進,架構如下:
下一次,我們來談談如何消除特殊情況。