軟體設計最根本的問題之一:兩個功能該放在一起,還是分開?

這個問題在系統的所有層級都會出現:function、method、class、service。

真實情境#

  • 緩衝(buffering)該不該與 stream 導向的檔案 I/O 類別放在一起?還是另立類別?
  • HTTP 請求的解析應該全部塞在一個方法?還是拆成多個方法(甚至多個類別)?

目標:降低整體複雜性與提升模組性#

「拆得越小越好」其實是個迷思。拆分本身會引入額外複雜性

拆分帶來的複雜性說明
元件數量本身越多越難追蹤;通常意味更多介面,每個介面都增加複雜度
管理開銷原本一個物件能搞定的,現在得管理多個物件
分離元件被放遠了 → 開發者更難同時看到它們;如果元件之間其實有依賴,反而更糟(甚至忽略掉依賴造成 bug)
重複原本一份的程式碼,可能在每個拆出來的元件裡都需要

把程式碼放在一起最有益的情況是:它們密切相關

不相關的東西最好分開。

兩段程式碼是否相關的判斷指標#

  • 共享資訊:兩段都依賴某種文件格式的語法
  • 一起使用(雙向):用其一通常會用其二
    • 反例:disk block cache 幾乎一定會用 hash table,但 hash table 在沒有 block cache 的場合也常用 → 不應綁在一起
  • 概念上重疊:能用一個簡單的高階範疇涵蓋(例如「字串操作」涵蓋子字串搜尋與大小寫轉換)
  • 不看另一段就難以理解

本章脈絡#

  1. 資訊共享時合併
  2. 能簡化介面時合併
  3. 為消除重複而合併
  4. 通用與特殊分離
  5. 拆分與合併方法(method 層級)

結語#

拆與合的決定,根據複雜性:選那個能帶來

  • 最佳資訊隱藏
  • 最少依賴
  • 最深介面

的結構。