把型別、成員身分或介面角色編進名字裡,曾經是為了替讀者省下查資料的功夫。但這些前綴是額外要維護的資訊:一旦變數改型別、名字沒跟著改,編碼本身就變成過期的謊言。在現代 IDE 已能即時顯示型別與作用域的年代,這些前綴只剩下視覺雜訊,卻仍要人花成本去維護。
🧠 Why It's a Problem
- 型別編碼會過期:
str、i_、list_這類把型別寫進名字的前綴,只要變數換了型別、名字沒同步更新,就從線索退化成誤導。IDE 本來就會顯示型別,這份資訊不該由人手動維護。 - 成員變數前綴是視覺雜訊:
m_description用m_標記「這是成員變數」,但現代編輯器已用顏色區分作用域,this.也能明確指涉——m_只是讓每個名字多背一段沒人需要的裝飾。 - 介面前綴洩漏了實作視角:在介面名前加
I(如IShapeFactory)等於強迫使用者關注「這是一個介面」這件實作細節,但使用者該關注的是抽象本身。若非得二選一,寧可讓實作類別去承擔裝飾,保持介面名乾淨。 - 前綴很快變成不看的贅字:讀者學會忽略名字開頭的固定前綴後,前綴就不再傳遞資訊,只是拉長名字、佔用視線——付出了維護成本卻不換得可讀性。
NOTE
這條原則和避免誤導是兄弟但不同:那頁談的是假線索(把不是 List 的東西叫 accountList、用 ProductInfo/ProductData 這種難分辨的近義名)。這頁談的是編碼慣例——就算 strName 真的是字串,str 前綴依舊是該被拿掉的雜訊。
⚖️ Case Study
前 — 名字裡塞滿編碼
// str 前綴標型別、m_ 前綴標成員、I 前綴標介面
class IShapeFactory {
// ...
}
class Person {
constructor(strName, iAge) {
this.m_strName = strName; // 型別編碼 + 成員前綴疊在一起
this.m_iAge = iAge;
}
getPhoneNumber() {
const phoneString = "555-0100"; // 型別編碼;日後改成物件,名字就騙人了
return phoneString;
}
}strName、m_strName、phoneString、IShapeFactory——每個名字都背著一段「它是什麼型別/什麼身分」的宣告,而這些正是 IDE 已經幫你顯示的東西。
後 — 名字只講抽象
// 介面名乾淨,把裝飾留給實作類別
class ShapeFactory {
// ...
}
class Person {
constructor(name, age) {
this.name = name; // 靠 this. 表明成員身分,不需要 m_
this.age = age;
}
getPhoneNumber() {
const phoneNumber = "555-0100"; // 名字描述「是什麼」,不描述「是什麼型別」
return phoneNumber;
}
}拿掉 str/m_/I 後,名字回到只講抽象:name、age、phoneNumber、ShapeFactory。型別與作用域交給工具即時顯示,維護的表面積就縮小了。
TIP
判準很簡單:如果一段前綴傳達的資訊,你的編輯器已經隨時顯示(型別、成員身分、介面 vs 實作),那它就是可以刪掉的編碼。名字的預算應該花在描述這個東西是什麼,而不是它怎麼被實作。
🔑 Takeaways
- 型別編碼(Hungarian notation,如
strName、iCount、phoneString)會隨型別變更而過期,且 IDE 已顯示型別——刪掉。 - 成員變數前綴
m_(m_description)是視覺雜訊,用this.與編輯器的作用域標示取代。 - 介面前綴
I(IShapeFactory)逼使用者看實作細節;讓介面名乾淨,裝飾留給實作類別。 - 現代 IDE 讓這些前綴變成純維護成本而非資訊;名字只該描述抽象,不描述型別或實作。
- 這頁講編碼(會製造雜訊的前綴慣例);假線索式的誤導請見避免誤導。
No notes yet — jot your takeaways or Q&A here.