這些實踐彼此支撐——一項實踐的弱點,被其他實踐的強項覆蓋。

一個合理的質疑#

且慢。上一章描述的實踐,沒有一項是獨特或原創的——自從有程式可寫以來,它們就一直被使用著。而其中大多數,都因為弱點日漸明顯,而被更複雜、更高開銷的實踐取代掉了。

那 XP 憑什麼不是一套天真幼稚的軟體途徑?在繼續之前,我們最好先說服自己:這些簡單實踐不會像數十年前害死軟體專案那樣害死我們。

答案是:指數型變更成本曲線的崩塌,讓所有這些實踐重新回到牌桌上。

每項實踐仍然帶著和從前一樣的弱點。但如果那些弱點現在能被其他實踐的強項補上呢?那我們或許就能安然無恙地把事情做得簡單。

本章以「你不可能……除非……」的句式重看一遍這些實踐:先點出通常讓該實踐站不住腳的原因,再說明其他實踐如何阻止它的壞效應壓垮專案。

規劃遊戲#

你不可能只帶著一份粗略的計畫就開始開發,也不可能不斷更新計畫——那太花時間,還會惹惱客戶。除非:

  • 更新計畫的是客戶自己,依據程式設計師提供的估算
  • 你在一開始就有足夠的計畫,能給客戶一個「未來幾年可能做到什麼」的粗略概念
  • 你做短發布,所以計畫上的任何錯誤最多只有幾週或幾個月的衝擊
  • 你的客戶與團隊同坐,能迅速察覺潛在的變化與改善機會

那麼,也許你就能帶著一份簡單的計畫開始開發,並沿路持續精煉它。

短發布#

你不可能在幾個月後就上線,更不可能以每天到每幾個月的週期發布新版本。除非:

  • 規劃遊戲幫你做的是最有價值的故事,所以連小系統都有業務價值
  • 你在持續整合,所以打包一次發布的成本極小
  • 你的測試把缺陷率壓得夠低,不必在放行前跑一輪冗長的測試週期
  • 你能做出簡單設計——只需滿足這一次發布,而不是滿足永遠

那麼,也許你就能在開發啟動後不久,開始做小發布。

隱喻#

你不可能只憑一個隱喻就開始開發——細節根本不夠,而且萬一你錯了怎麼辦?除非:

  • 你能從真實程式碼與測試迅速得到具體回饋,知道這個隱喻在實務上管不管用
  • 你的客戶能自在地用這個隱喻談論系統
  • 重構,以持續精煉自己對「這個隱喻在實務上意謂什麼」的理解

那麼,也許你就能只憑一個隱喻開始開發。

簡單設計#

你不可能只做剛好夠今天程式碼用的設計——你會把自己設計進死角,然後卡住,無法繼續演化系統。除非:

  • 習慣重構,所以做變更不是煩惱
  • 你有清楚的整體隱喻,所以確信未來的設計變更會傾向沿著收斂的路徑走
  • 與夥伴一起寫程式,所以有信心自己做的是簡單設計,而不是愚蠢設計

那麼,也許你就能安然地「為今天做出最好的設計」。

測試#

你不可能寫那麼多測試,太花時間了。而且程式設計師不會寫測試。除非:

  • 設計盡可能簡單,所以寫測試沒那麼困難
  • 與夥伴一起寫程式——你想不出下一個測試時夥伴想得出;而夥伴想混過測試時,你可以溫柔地把鍵盤搶過來
  • 看到測試全部通過時,你感覺很好
  • 客戶看到自己的測試全部通過時,對系統感覺很好

那麼,也許程式設計師與客戶就會寫測試。

更何況,不寫自動化測試的話,XP 的其餘部分效果會差得多。

重構#

你不可能一直重構系統的設計——太耗時、太難控制,而且極可能弄壞系統。除非:

  • 你習慣集體所有權,所以不介意在任何需要的地方做變更
  • 你有編碼標準,所以不必在重構前先重排格式
  • 結對,所以比較可能有勇氣處理棘手的重構,也比較不會弄壞東西
  • 你有簡單設計,所以重構比較容易
  • 你有測試,所以比較不會在不知情下弄壞東西
  • 你有持續整合,所以萬一你在遠處不小心弄壞了什麼、或你的重構與別人的工作衝突,你在幾小時內就會知道
  • 休息充足,所以更有勇氣、也更不容易犯錯

那麼,也許你就能在每次看到「讓系統更簡單、減少重複、溝通更清楚」的機會時重構。

結對程式設計#

你不可能所有正式程式碼都成對寫,那太慢了。而且萬一兩個人處不來怎麼辦?除非:

  • 編碼標準減少了雞毛蒜皮的爭吵
  • 每個人都清爽而休息充足,進一步降低了那些……嗯……無益討論的機率
  • 一對一起寫測試,讓他們在啃實作的硬肉之前有機會對齊理解
  • 一對有隱喻作為命名與基本設計決策的地基
  • 一對在簡單設計中工作,所以兩人都能理解正在發生什麼

那麼,也許你就能成對寫出所有正式程式碼。

更何況,人們單獨寫程式時更容易犯錯、更容易過度設計,也更容易草草跳過其他實踐——尤其在壓力之下。

集體所有權#

你不可能讓每個人都有可能改動任何地方的任何東西——大家會左右開弓地弄壞東西,整合成本也會暴漲。除非:

  • 你在夠短的時間內整合,所以衝突的機會下降
  • 寫測試也跑測試,所以意外弄壞東西的機會下降
  • 結對,所以比較不會弄壞程式碼,而程式設計師也更快學會「哪些東西改了有好處」
  • 遵守編碼標準,所以不會陷入那可怕的大括號戰爭(Curly Brace Wars)

那麼,也許你就能讓任何人在看到改善機會時,改動系統中任何地方的程式碼。

更何況,沒有集體所有權,設計的演化速率會急遽變慢。

持續整合#

你不可能只工作幾小時就整合——整合太花時間,衝突太多,而且太容易意外弄壞東西。除非:

  • 你能快速跑完測試,所以知道自己沒弄壞任何東西
  • 結對,所以要整合的變更流只有一半條
  • 重構,所以有更多更小的片段,降低了衝突的機會

那麼,也許你就能在幾小時後整合。

更何況,不快速整合的話,衝突的機會會上升,而整合成本會陡峭地攀高。

每週 40 小時#

你不可能只工作每週 40 小時——那創造不出足夠的業務價值。除非:

  • 規劃遊戲持續餵給你更有價值的工作
  • 規劃遊戲加上測試的組合,降低了「事情比想像中多」這類討厭意外的頻率
  • 整套實踐幫你以最高速度寫程式,所以你根本沒有更快的可能

那麼,也許你就能在每週 40 小時內產出足夠的業務價值。

更何況,團隊若不能保持清爽與活力,就無法執行其餘的實踐。

現場客戶#

你不可能讓一位真實客戶全職坐在團隊裡——他們在別處能為業務產出多得多的價值。除非:

  • 他們能透過撰寫功能測試為專案產出價值
  • 他們能透過替程式設計師做小尺度的優先序與範圍決策為專案產出價值

那麼,也許他們投入這個專案,反而能為公司產出更多價值。

更何況,團隊裡若沒有客戶,就必須把計畫排得更遠、在不確知「該滿足哪些測試、可以忽略哪些測試」的情況下寫程式——這等於替專案追加風險。

編碼標準#

你不可能要求團隊照一套共同標準寫程式——程式設計師個人主義深重,寧可辭職也不肯把大括號換個位置。除非:

  • XP 這一整套讓他們更可能成為一支贏球隊伍的成員

那麼,也許他們就願意把自己的風格稍微彎一下。

更何況,沒有編碼標準,額外的摩擦會顯著拖慢結對程式設計與重構。

結論:豐富性來自互動#

圖 4:實踐彼此支撐——圖中兩項實踐之間的連線,代表這兩項實踐相互強化

作者說他不想一開始就秀出這張圖,因為那會讓 XP 看起來很複雜。

個別的零件是簡單的——豐富性來自零件之間的互動。