與管理策略不同,開發策略是對傳統智慧的激進背離——我們今天為今天的問題精心打造解法,並相信自己明天有能力解決明天的問題。

一切看起來都像寫程式#

XP 用「程式設計」作為其活動的隱喻——也就是說,你做的每件事在某種意義上都像在寫程式。XP 中的程式設計就是程式設計,只是加上幾樣小東西,例如自動化測試。

然而,如同 XP 的其餘部分,XP 的開發簡單得騙人。所有零件都簡單到足以解釋清楚,但執行它們很難。恐懼會侵入;壓力之下,舊習慣會回來。

開發策略從迭代規劃開始;持續整合減少開發衝突,並為一段開發歷程創造出自然的結束點;集體所有權鼓勵整個團隊讓整個系統變得更好;最後,結對程式設計把整個流程綁在一起。

持續整合#

沒有任何程式碼能未整合地擱置超過幾小時。 每一段開發歷程結束時,程式碼都與最新發布版整合,而且所有測試必須 100% 通過。

在持續整合的極端邊界上,你每改一個方法,變更就會即刻反映到其他所有人的程式碼裡。撇開支撐這種風格所需的基礎設施與頻寬不談,這樣效果並不好

你在開發時,會想假裝自己是專案上唯一的程式設計師——全速前進,無視你所做的變更與其他人碰巧在做的變更之間的關係。讓變更在你的立即控制之外發生,會粉碎這個幻覺。

為什麼是「幾小時」#

在幾小時後(絕不超過一天)整合,同時取得兩種風格的多數好處——單人程式設計的專注,以及即時整合的安全:

  • 開發時,你可以表現得像你和夥伴是專案上唯一的一對,想在哪裡改就在哪裡改
  • 然後你換上另一頂帽子:作為整合者,工具會告訴你類別或方法定義上哪裡發生碰撞;而跑測試會讓你察覺語意上的碰撞

如果整合要花上好幾小時,這種工作風格就不可能成立。因此:

  • 必須有支援快速「整合/建置/測試」循環的工具
  • 必須有一套幾分鐘內跑得完、且相當完整的測試套件
  • 修復碰撞所需的努力不能太大

而這不是問題:持續重構的效果,是把系統打碎成大量小物件與小方法,這降低了兩對程式設計師同時改動同一個類別或方法的機會;就算真的發生,調和變更所需的努力也很小——因為每一邊都只代表幾小時的開發

持續整合的三重收益#

  • 大幅降低專案風險——如果兩個人對一段程式碼的樣貌或運作有不同想法,你在幾小時內就會知道;你永遠不必花好幾天追一個「過去幾週某個時點被製造出來」的 bug。
  • 讓最終上線變成非事件——所有整合的練習,在建立最終產出時派上大用場。「正式建置(production build)」根本沒什麼大不了的:輪到它的時候,團隊裡每個人閉著眼睛都做得出來,因為他們已經每天做了好幾個月。
  • 提供寶貴的人性節奏——做一項任務做到一半時,你腦中有一百件事。工作到一個自然的斷點(待辦卡上再也沒有小項目了)然後整合,就給了開發一種節奏:學習/測試/寫程式/發布。這幾乎像呼吸一樣——你形成一個想法、表達它、把它加進系統;現在你的心思清空了,準備好迎接下一個想法。

持續整合有時會迫使你把一項任務的實作拆成兩段歷程。我們接受這帶來的開銷(必須記住做了什麼、還剩什麼)。

而在這中間的空檔,你可能會頓悟到究竟是什麼讓第一段歷程進行得那麼慢。 於是你用一點重構開啟下一段歷程,第二段歷程的其餘部分就順暢多了。

集體所有權#

集體所有權是這個看似瘋狂的想法:任何人可以在任何時候改動系統中任何一段程式碼。

而且,你還必須一次只整合幾小時份量的變更。當然,那正是你會做的事。

集體所有權帶來四個效果:

  • 複雜的程式碼活不久——因為每個人都習慣在系統各處張望,這種程式碼遲早(而且是早)會被發現。而一旦被發現,就會有人試著簡化它。如果簡化失敗(測試失敗為證),程式碼就會被扔掉——即使如此,也多了一個原始那對之外的人,理解了為什麼這段程式碼可能必須複雜。不過更常見的是,簡化成功了,或至少有一部分成功了。
  • 從一開始就阻止複雜程式碼進入系統——如果你知道別人很快(幾小時內)就會看到你此刻在寫的東西,你在放入一個「無法立即說出正當理由」的複雜度之前,會三思。
  • 增強你在專案上的個人力量感——在 XP 專案裡,你永遠不會被別人的愚蠢卡住。你看到什麼擋路,你就把它移開。如果你選擇暫時忍受某個東西因為那樣比較省事,那是你的事,但你永遠不會被卡死。所以你永遠不會產生那種「要不是得應付這些白痴,我早就把工作做完了」的感覺——少一份挫折,離清晰思考近一步。
  • 把系統知識散播到整個團隊——不太可能出現「只有兩個人懂」的系統部位(而且至少得是一對,這已經好過「一個聰明程式設計師挾持所有其他人」的常態)。這進一步降低了專案風險。

結對程式設計#

結對程式設計實在該有一本自己的書。這是一項微妙的技藝,你可以用餘生去把它練好。

結對程式設計不是什麼#

  • 不是一個人寫程式、另一個人看著。 光是看人寫程式,大概和看沙漠裡的草枯死一樣有趣。結對程式設計是兩個人之間的對話——他們同時在寫程式(以及分析、設計、測試),並一起理解如何寫得更好。這是一場多層次的對話,由電腦協助、也聚焦於電腦。
  • 不是家教課。 有時一對之中有一位經驗遠勝另一位。這種時候,最初幾次會議看起來確實很像家教:資淺的夥伴會問很多問題、打很少字。但很快地,資淺夥伴就會開始抓到愚蠢的小錯誤,例如不對稱的括號,而資深夥伴會注意到這份幫助。再過幾週,資淺夥伴會開始撿起資深夥伴使用的較大模式,並注意到偏離這些模式的地方。通常在幾個月內,兩人之間的落差就不像一開始那麼明顯了:資淺夥伴打字更頻繁,這一對也注意到彼此各有強項與弱項——生產力、品質與滿意度同步上升
  • 不是黏在同一條臀縫上。 有時你在開始一項任務時會找特定的夥伴,但更常見的是你就找一個有空的人。而如果你們兩人各有任務,就約定早上做一項、下午做另一項。

處不來怎麼辦#

有人拒絕結對怎麼辦? 他可以選擇學著像團隊其他人那樣工作,也可以選擇到團隊之外找工作。XP 不適合每個人,也不是每個人都適合 XP。

不過,你不必在做極限開發的第一天就開始全職結對。跟其他一切一樣,你得一點一點朝它前進:先試一小時;如果行不通,試著弄清楚哪裡出了問題,然後再試一小時。

為什麼結對對 XP 有效#

第一項價值是溝通,而少有溝通形式比面對面更密集。

作者喜歡用一池水的比喻:當團隊中某人學到一則重要的新資訊,就像在水裡滴入一滴染劑。由於配對不斷輪換,資訊會迅速擴散到整個團隊,正如染劑散布到整池水。

但與染劑不同的是——資訊在擴散的過程中會變得更豐富、更濃烈,因為它被團隊中每個人的經驗與洞見所豐富。

依作者的經驗,結對程式設計比「把工作分給兩個程式設計師、再整合結果」更有生產力。結對常是想採用 XP 的人的卡關點。作者只能說:先把它練好,然後試一次「所有正式程式碼都結對」的迭代,再試一次「一切都單獨寫」的迭代——然後你就能自己做決定。

即使生產力沒有更高,你仍然會想結對,因為產出的程式碼品質高得多。當一位夥伴忙著打字,另一位在更策略性的層次思考:

  • 這條開發路線要往哪裡去?
  • 它會不會走進死胡同?
  • 有沒有更好的整體策略?
  • 有沒有重構的機會?

結對是其他實踐的保險#

結對程式設計另一個強大之處是:有些實踐沒有它就不會運作。

壓力之下,人們會退化:他們會跳過寫測試、會拖延重構、會迴避整合。但有夥伴看著,就算你想草草放掉其中一項實踐,你的夥伴八成不會。

這不是說結對就不會犯流程上的錯誤——他們當然會,否則你就不需要教練了。但一對人忽視「對團隊其餘成員的承諾」的機率,遠小於單獨工作時。

最後,結對程式設計的對話性質也提升了軟體開發流程本身。你很快就學會在許多不同層次上交談:此處這段程式碼、系統別處類似的程式碼、過去類似的開發歷程、多年前類似的系統、你們正在使用的實踐以及它們如何能變得更好。