程式大小作為關鍵資源#

在 1960 至 70 年代,記憶體是極為昂貴且有限的資源。Brooks 指出,程式的大小(size)必須像時程和預算一樣受到嚴格的管理。即使在今天記憶體相對充裕的時代,這個原則依然適用——只是「稀缺資源」的對象從記憶體變成了快取、頻寬、電池壽命或啟動時間。

程式大小不會自己控制自己。如果不從一開始就設定預算並嚴格追蹤,系統會不可避免地膨脹到超出限制。

大小預算#

Brooks 主張,架構師必須為每個元件設定大小目標,就像設定時程里程碑一樣。這些預算不僅包括核心記憶體的使用量,還應涵蓋磁碟存取次數(I/O 效能)等關鍵資源。

管理者在大小控制方面的職責是:

  • 從一開始就定義預算:在設計階段就為每個模組分配記憶體額度
  • 持續追蹤實際值與預算的差距:定期比較實際使用量和預算
  • 及早發出警報:當某個模組超標時,立即採取行動而非等到整合時才發現問題

這種做法要求在專案初期就做出看似武斷的分配決定。但 Brooks 認為,有預算總比沒有預算好——即使初始分配不夠精確,它至少提供了一個追蹤和調整的基礎。

功能與大小的取捨#

當程式無法塞進分配的記憶體空間時,就必須做出艱難的取捨。架構師需要判斷:哪些功能以最少的位元組提供最大的價值?

這是一個需要智慧和勇氣的決策。有時候,砍掉一個看起來很重要的功能,反而能讓系統整體更加精煉和有效。Brooks 強調,這些取捨決策應該由架構師而非個別程式設計師來做,因為只有架構師能從全局的角度評估每個功能的相對價值。

功能的取捨不是失敗的標誌,而是成熟的工程判斷。最好的系統不是擁有最多功能的系統,而是在有限資源下提供最大價值的系統。

空間與時間的取捨#

Brooks 提到了計算機科學中的經典原則:空間與時間的取捨(space-time tradeoff)。你可以用更多記憶體換取更快的執行速度,反之亦然。

例如:

  • 查表法(lookup table)用額外的記憶體空間來避免重複計算,換取速度
  • 即時運算(on-the-fly computation)用較少的記憶體但花費更多的 CPU 時間

團隊必須有意識地做出這些取捨,而非讓它們在無人注意的情況下自然發生。管理者應該明確指定哪些場景優先考慮速度、哪些優先考慮空間。

表達方式即程式設計的本質#

Brooks 引用了他的導師的一句名言,這句話可以說是本章最深刻的洞見:

「讓我看你的流程圖但隱藏你的表格,我會持續困惑。讓我看你的表格,我通常就不需要你的流程圖了;它們會不言自明。」

這句話道出了一個根本真理:資料結構(表達方式)比程式碼更重要。程式的複雜度主要來自它所操作的資料結構,而非控制流程。選擇正確的資料表達方式,往往能讓演算法自然而然地變得簡單明瞭。

當你面對一段複雜難懂的程式碼時,與其試圖簡化邏輯流程,不如先重新審視它的資料結構。很多時候,換一種資料表達方式就能讓整個問題迎刃而解。

控制程式大小的技術#

Brooks 提出了幾種控制程式大小的實用策略:

使用高階語言#

高階語言的編譯器通常能產生比手寫組合語言更緊湊的程式碼。雖然這聽起來違反直覺,但編譯器能夠利用系統性的最佳化技術,而人類程式設計師往往只能做局部的最佳化。

共享公共程式碼#

將通用的功能抽取到共享函式庫中,避免每個模組各自實作相似的邏輯。這不僅節省空間,還提高了程式碼的一致性和可維護性。

共享資料緩衝區#

透過分時使用(overlay)或分頁(paging)機制,讓不同的功能模組共享同一塊記憶體緩衝區。這種技術在記憶體有限的系統中特別重要。

精心設計資料表達#

這是最根本也最有效的策略。花時間在資料結構的設計上,往往能帶來程式大小和複雜度的大幅縮減。一個巧妙的資料結構可以同時節省空間和簡化程式碼。

不要在專案後期才開始擔心程式大小。到那時候,架構已經定型,資料結構已經選定,能夠騰挪的空間非常有限。大小控制必須從第一天開始。

本章重點#

  • 程式大小是需要主動管理的關鍵資源,必須像時程和預算一樣設定目標並追蹤
  • 架構師應為每個元件分配大小預算,管理者應持續監控實際值與預算的差距
  • 功能與大小的取捨是成熟的工程判斷——最好的系統不是功能最多的系統
  • 空間與時間的取捨必須有意識地進行,而非任由其自然發生
  • 資料結構比程式碼更重要——選對表達方式,演算法就會自然簡化
  • 高階語言、共享程式碼、共享緩衝區和精心設計的資料結構是控制大小的四大策略