最好的模組:強大的功能藏在簡單的介面之後。 作者把這種模組稱為「深(deep)」。
視覺化:模組的「深度」#
把每個模組想像成一個矩形:

Figure 4.1: 深模組與淺模組——好的模組讓大量功能透過簡單介面被存取;淺模組介面複雜卻沒藏多少複雜性
- 矩形面積 ∝ 模組實作的功能量
- 矩形上邊長度 ∝ 介面的複雜度
- 好模組是「深」的:大量功能藏在短短的上邊(簡單介面)後面
從成本與效益看深度#
- 效益:模組提供的功能
- 成本:模組對系統其他部分施加的複雜性 = 介面
- 介面越小、越簡單,引入的複雜性越少
介面是好東西,但更多 / 更大的介面不一定更好!
最好的模組是「效益最大、成本最小」。
範例:Unix I/O#
Unix(與 Linux)對檔案 I/O 的介面是深介面的經典:只有五個基本系統呼叫,簽章極其簡單。
int open(const char* path, int flags, mode_t permissions);
ssize_t read(int fd, void* buffer, size_t count);
ssize_t write(int fd, const void* buffer, size_t count);
off_t lseek(int fd, off_t offset, int referencePosition);
int close(int fd);open接受階層式檔名,回傳整數 file descriptorread/write在使用者緩衝區與檔案之間搬資料lseek用於隨機存取(預設是循序存取)close結束存取
而現代實作需要數十萬行程式碼,要處理:
- 檔案在磁碟上如何表示以支援高效存取
- 目錄如何儲存?階層式路徑名如何解析?
- 權限如何強制執行?
- 中斷處理常式與背景程式如何分工、如何安全溝通?
- 多檔案併發存取的排程策略?
- 最近存取的資料如何快取?
- 如何整合磁碟、快閃記憶體等不同二級儲存裝置?
所有這些問題對呼叫端完全不可見。
Unix I/O 的實作多年來歷經劇烈演化,但這五個基本系統呼叫始終沒變。
範例:垃圾回收(Garbage Collection)#
Go、Java 等語言的垃圾回收器是另一個深模組:
- 介面是零——它在背景無聲運作回收未使用記憶體
- 加入 GC 反而縮小了系統整體介面(移除了「釋放物件」的介面)
- 實作非常複雜,但對語言使用者完全隱藏
深模組的價值#
Unix I/O 與 GC 都是強大的抽象範例:
- 容易使用(介面簡單)
- 隱藏巨大實作複雜性