軟體設計最根本的問題之一:兩個功能該放在一起,還是分開?
這個問題在系統的所有層級都會出現:function、method、class、service。
真實情境#
- 緩衝(buffering)該不該與 stream 導向的檔案 I/O 類別放在一起?還是另立類別?
- HTTP 請求的解析應該全部塞在一個方法?還是拆成多個方法(甚至多個類別)?
目標:降低整體複雜性與提升模組性#
「拆得越小越好」其實是個迷思。拆分本身會引入額外複雜性:
| 拆分帶來的複雜性 | 說明 |
|---|---|
| 元件數量本身 | 越多越難追蹤;通常意味更多介面,每個介面都增加複雜度 |
| 管理開銷 | 原本一個物件能搞定的,現在得管理多個物件 |
| 分離 | 元件被放遠了 → 開發者更難同時看到它們;如果元件之間其實有依賴,反而更糟(甚至忽略掉依賴造成 bug) |
| 重複 | 原本一份的程式碼,可能在每個拆出來的元件裡都需要 |
把程式碼放在一起最有益的情況是:它們密切相關。
不相關的東西最好分開。
兩段程式碼是否相關的判斷指標#
- 共享資訊:兩段都依賴某種文件格式的語法
- 一起使用(雙向):用其一通常會用其二
- 反例:disk block cache 幾乎一定會用 hash table,但 hash table 在沒有 block cache 的場合也常用 → 不應綁在一起
- 概念上重疊:能用一個簡單的高階範疇涵蓋(例如「字串操作」涵蓋子字串搜尋與大小寫轉換)
- 不看另一段就難以理解
本章脈絡#
- 資訊共享時合併
- 能簡化介面時合併
- 為消除重複而合併
- 通用與特殊分離
- 拆分與合併方法(method 層級)
結語#
拆與合的決定,根據複雜性:選那個能帶來
- 最佳資訊隱藏
- 最少依賴
- 最深介面
的結構。