複雜度的本質 (The Nature of Complexity)

★★★★★Draft

FromA Philosophy of Software Design

📚 From the Books

複雜度的本質 (The Nature of Complexity)Complexity

軟體設計的核心目標是降低複雜度。要對付敵人,得先認得它。複雜度不是某一顆巨石,而是**依賴(dependencies)模糊(obscurity)**日積月累的結果——累積到一定程度,就以三種症狀現身:變更放大、認知負擔、未知的未知,最終讓修改既有程式碼變得困難又高風險。

🧠 複雜度長什麼樣(症狀)

複雜度不必抽象地談,它會用三種具體症狀讓你認出來:

NOTE

辨識複雜度是設計者最關鍵的能力之一:能在投入大量心力之前就提早察覺問題,也能在多個替代方案間做出較好的判斷。關鍵洞見是——判斷一個設計是否簡單,比親手寫出簡單的設計來得容易;而這份判斷力反過來會引導你的設計哲學朝簡潔靠攏。

⚖️ 複雜度從哪來(兩個成因)

複雜度源自兩件事的累積:依賴模糊

依賴 (dependency) — 一段程式無法被單獨理解或修改

當一段程式碼要正確運作,必須配合另一段程式碼時,兩者之間就存在依賴。依賴讓你無法只盯著局部就改對,也正是變更放大的來源。

// 同一個「稅率」概念散落在三處:彼此隱性依賴
function priceWithTax(p) { return p * 1.05; }
function shippingWithTax(s) { return s * 1.05; }
function refundTax(amount) { return amount - amount / 1.05; }

// 稅率一改 5% → 8%,三個函式都得同步動手,漏一個就出錯

改一件事卻要動三個地方——這就是依賴帶來的變更放大。

模糊 (obscurity) — 重要資訊沒有擺在明顯處

當一段程式的重要資訊不明顯時,就產生模糊。讀者看不出該知道什麼,於是留下未知的未知

// t 的單位是什麼?毫秒?秒?呼叫端無從得知
function retry(fn, t) {
  setTimeout(fn, t);
}

// 呼叫端只能猜,猜錯了也不會有人告訴你
retry(sync, 30); // 30 毫秒?還是想寫 30 秒?

當「該知道的事」沒有寫在明顯的地方,改動就變成一場賭博。

TIP

兩個成因彼此呼應:依賴大多引發變更放大,模糊大多引發未知的未知,而兩者都會加重認知負擔。想降低複雜度,就是設法減少依賴、消除模糊。深模組是達成這件事的重要手段——見 深模組 (Deep Modules)

漸進累積:複雜度不是一次造成的

複雜度很少是某個災難性決策一次鑄成的,而是一點一滴累積起來的:每次為了趕工多加一個依賴、每次省略一段本該寫清楚的資訊,單看都微不足道,累積起來卻讓系統逐漸難以理解與修改。

IMPORTANT

正因為複雜度是漸進累積的,就沒有哪一次改動可以「事後一次清乾淨」。每一次小的取捨都算數——這也是為什麼要在每次改動當下就守住簡潔。

🔑 Takeaways

✍️ My Notes

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

📖 Further Reading