深模組 (Deep Modules)

★★★★★Reviewed

FromAPoSD

📚 From the Books

深模組 (Deep Modules)Complexity

Ousterhout 的核心命題:好模組是「深的」——介面小,功能多。模組的價值 ≈ 它隱藏的複雜度(功能)÷ 它強加給使用者的複雜度(介面)。介面窄、實作厚,這個比值才高。

🧠 Why It's a Problem

NOTE

經典反例是 Java I/O:要開一個帶緩衝的檔案串流得 new BufferedInputStream(new FileInputStream(path))——緩衝這個「幾乎人人都要」的細節被暴露在介面上。Unix 的 open / read / write / close 則相反:五個簡單呼叫,背後藏著排程、快取、權限、裝置驅動的巨量複雜度。那就是深。

⚖️ 設計對照(深 vs. 淺)

淺模組 — 介面幾乎等於實作,沒藏住複雜度
// 介面把每個內部步驟都攤開,呼叫端得自己編排、自己懂順序
class TextProcessor {
  splitIntoLines(text) { /* ... */ }
  tokenizeLine(line) { /* ... */ }
  stripWhitespace(tokens) { /* ... */ }
  countTokens(tokens) { /* ... */ }
}

// 呼叫端被迫了解全部內部結構
const p = new TextProcessor();
const lines = p.splitIntoLines(text);
const all = lines.flatMap(l => p.stripWhitespace(p.tokenizeLine(l)));
const total = p.countTokens(all);

四個方法、四個概念,使用者扛下全部編排責任。模組沒有替任何人省事。

深模組 — 窄介面藏住厚實作
// 介面只有一個意圖;分行、tokenize、清理、計數全藏在裡面
class TextProcessor {
  countWords(text) {
    return text
      .split('\n')
      .flatMap(line => this.#tokenize(line))
      .filter(Boolean).length;
  }
  #tokenize(line) { /* 私有:使用者永遠不需要知道 */ }
}

const total = new TextProcessor().countWords(text);

一個方法、一個概念。內部要換演算法、加 Unicode 處理、改格式,呼叫端一行都不用動——複雜度被關在門後。

TIP

設計時反覆問:這個介面有沒有把複雜度真的藏起來,還是只是把它轉手給呼叫端? 若是後者,這個抽象不值得它的成本。

🔑 Takeaways

✍️ My Notes

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

📖 Further Reading