計畫丟掉一個#
Brooks 在本章開宗明義地提出一句名言:
「計畫丟掉一個吧;反正你終究會這麼做。」(Plan to throw one away; you will, anyhow.)
無論是否有意為之,你的第一個系統版本都將是一個試驗品。它可能太慢、太大、太笨拙,或者三者兼具。關鍵問題不在於是否要建構一個試驗系統(pilot system),而在於是否事先計畫好將它丟掉,還是把這個試驗品硬塞給客戶使用。
如果你不主動計畫丟掉第一個版本,你的客戶將被迫替你承受這個實驗品的代價。最終你仍然會重寫,只是時間更晚、代價更高。
先導工廠與規模放大#
化學工程師早已學到一個教訓:不能直接從實驗室規模跳到工廠規模。在兩者之間,他們會建造一座先導工廠(Pilot Plant),在真實條件下測試製程,驗證假設,然後才投入全面生產。
軟體開發應該採取同樣的策略。然而,軟體工程師卻經常試圖將第一次嘗試的系統直接交付為最終產品。Brooks 認為,這種做法注定會導致一個充滿缺陷、架構不良的系統。先導系統的目的是學習——學習需求的真正含義、學習技術方案的可行性、學習使用者的真實行為。
唯一不變的就是變化本身#
Brooks 指出,變化(change)是軟體開發中唯一可以確定的事實。一旦系統開始運作,使用者就會發現他們真正想要的東西與最初描述的需求不同。技術環境在持續演進,硬體在更新,使用者期望在改變。
這意味著:
- 需求會在開發過程中改變
- 使用者只有在看到系統運行後,才能真正理解自己的需求
- 設計者必須從一開始就預期變化,而不是試圖凍結需求
為變化而設計系統#
既然變化不可避免,系統的架構就必須為變化做好準備。Brooks 提出以下策略:
模組化設計#
- 使用精確定義的模組介面(well-defined module interfaces),使得模組可以被獨立替換
- 將最可能改變的部分隔離在獨立的模組中
- 保持模組之間的低耦合(low coupling)
版本與文件#
- 使用版本編號(version numbering)來追蹤系統的演進
- 確保每個版本都有完整的文件記錄
- 量化變更(quantize changes),將多個小變更集中在特定版本中釋出,而非持續零散地修改
設計的前瞻性#
- 在設計時就考慮未來的擴展方向
- 為內部資料結構預留彈性
- 在關鍵的決策點使用抽象層,以便日後替換實作方式
為變化而設計,不是要你預測所有可能的變化,而是要讓系統在需要改變時,能夠以最小的代價完成修改。
為變化而組織團隊#
Brooks 認為,不只系統需要為變化做好準備,組織本身也必須為變化而設計。
雙軌晉升制度#
傳統組織中,技術人員唯一的晉升路徑是轉入管理職。這造成了兩個問題:
- 優秀的技術人才被迫離開他們擅長的領域
- 管理階層充斥著不適合管理的技術人員
Brooks 主張建立雙軌制度(dual ladder):
- 技術軌:資深程式設計師、技術架構師、技術研究員——薪資與地位與管理職對等
- 管理軌:專案經理、部門經理——專注於人員與流程管理
人員的靈活調配#
組織必須能夠靈活地將人員在不同角色之間調動。當一個子系統的設計階段完成時,其設計者可能需要轉移到另一個子系統。這要求:
- 管理者願意讓優秀人才流動
- 個人願意接受角色的變化
- 組織文化支持而非懲罰這種流動
前進兩步,後退一步#
Brooks 以熵(entropy)的概念來描述系統維護的困境。
每次修復一個缺陷(defect),都有相當高的機率會引入新的缺陷。根據 Brooks 引用的數據,對正在運行的系統進行一次修復後,引入新缺陷的機率約為 20% 到 50%。因此,系統在經歷一系列修復之後,實際上只是在「前進兩步,後退一步」。
隨著時間推移:
- 修復不斷引入新的問題
- 系統的模組邊界逐漸被破壞
- 最初的設計意圖越來越難辨認
前進一步,後退一步#
更糟糕的情況是,隨著系統不斷被修補和擴充,整體複雜度持續上升。到了某個臨界點,每一次修改都會引入等量甚至更多的新問題——此時系統實際上是「前進一步,後退一步」,甚至原地踏步。
這暗示了一個令人不安的結論:任何系統最終都會退化到必須從頭重寫的地步。Brooks 認為,系統設計應該從一開始就認知到這個事實,而不是期望一個系統能夠永遠維護下去。
系統的熵只會增加,不會自行減少。不斷修補一個老舊的系統,最終的成本會超過從頭重建。問題不在於「是否」需要重寫,而在於「何時」需要重寫。
本章重點#
- 第一個版本是學習工具,不是最終產品——應該計畫將它丟掉
- 變化是軟體開發中唯一的常數,系統和組織都必須為此做好設計
- 模組化、版本管理、精確的介面定義是應對變化的核心策略
- 組織需要雙軌晉升制度和靈活的人員調配機制
- 系統維護過程中熵不斷增加,最終必須面對重寫的現實