程式碼要一目瞭然 (Code Should Be Obvious)

★★★★Draft

FromA Philosophy of Software Design

📚 From the Books

程式碼要一目瞭然 (Code Should Be Obvious)Complexity

模糊(obscurity)是複雜性的兩大成因之一,對策就是把程式碼寫得顯而易見:讀者能快速掃過、不必多想,而且第一直覺就是對的。關鍵在於——「顯而易見」不由作者宣稱,而是由讀者的腦袋來判斷。

🧠 Why It's a Problem

TIP

別人喊「這段不顯而易見」時,別急著辯解。試著搞懂是什麼讓它變模糊,下次就能寫出更好的程式碼。

⚖️ 什麼讓程式碼變得不顯而易見

讓程式碼顯而易見有幾條正面途徑:好的命名(見 意圖揭示的命名)、一致性(相似的事用相似方式做,讀者能套用既有模式、不必細讀就下安全結論)、善用空白(用空行分隔邏輯區塊、讓註解更顯眼),以及在無法避免的模糊處補上戰略性註解。這裡聚焦反面——書中點名的幾個「把程式碼變模糊」的常見來源。

通用容器 — 元素被塞進泛用名,看不出真實意義
// 用通用 pair 回傳兩個值:呼叫端只能看到 first / second
function advanceTerm(state) {
  return { first: state.currentTerm, second: false };
}

const r = advanceTerm(state);
// r.first 是什麼?r.second 又代表什麼?得回去翻實作才知道
if (!r.second) retry(r.first);

通用容器對「寫的人」方便,卻對所有後來的讀者製造混亂——名字(first/secondgetKey/getValue)完全藏住了元素的真實意義。

專用結構 — 有意義的名字,宣告處還能附文件
// 為這個用途定義專屬結構:名字自己會說話
function advanceTerm(state) {
  return { currentTerm: state.currentTerm, electionWon: false };
}

const { currentTerm, electionWon } = advanceTerm(state);
if (!electionWon) retry(currentTerm);

多花幾分鐘定義專用結構,換來的是明顯易懂——這正呼應書中的原則:軟體應為「易讀」設計,而不是為「易寫」設計。

CAUTION

當程式碼的意義與行為無法被快速看懂,這就是一面紅旗,通常代表有重要資訊沒被立即呈現給讀者。書中點名的模糊來源包括:

  • 事件驅動程式設計:handler 從不被直接呼叫,事件模組透過函式指標/介面間接觸發,連看到呼叫點都猜不出會跑哪個 handler,控制流極難追蹤。對策是在每個 handler 的介面註解裡說明它何時被呼叫。
  • 通用容器(如 Pair):元素被塞進泛用名,真實意義消失。
  • 宣告型別與實際分配型別不一致:例如宣告成 List 卻分配 ArrayList——讀者只看宣告,會誤判它的效能與執行緒安全特性。最好讓兩者一致。
  • 違反讀者預期的程式碼:例如 main 結束了,建構式偷偷啟動的執行緒卻還在跑。務必用文件(介面註解+現場一行短註解)補上。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading