觀察到的習慣

不需凍結版本

使用主幹開發的日常生活中,開發者每天和每週工作通常不會有太大變化。特別是,沒有「我們即將發布,所以讓我們凍結版本」,通常也不會出現接近發布時,開發速度會變慢的狀況。當然,團隊中的幾個開發者可能會在發布前被分配去修復錯誤,而其他人仍將保持全速工作。

一般來說,主幹是一個快速大量提交的地方,開發者的習慣是確保所有的程式碼都準備好可以隨時上線。如果一個團隊每年發布 12 個版本,那麼按需求建立的發布分支會是唯一會看到是處於「凍結」狀態的,因為開發者不會在那裡繼續開發。請參閱為發布建立分支

不變的日常生活

排除會議的影響,開發者無論周幾或月份的哪一周,提交和推送變更的速度和目標位置1都是一致的。這加強了上述「不需凍結版本」規則。當然,部分團隊成員可能會專注於即將發布的版本(在主幹修復錯誤,以及挑選既有的提交到發布分支),但大多數成員應該專注於「照常進行」的未來版本功能的開發。

快速審查

實踐主幹開發的團隊很清楚,一旦他們的提交被推送到主幹,就會受到其他成員的檢視。他們不想拖延,而是希望能提前進行這項檢查,因此可能更喜歡在程式碼變更的當下進行配對開發,或者在變更提交到主幹合併之前,請同事進行程式碼審查。

緊跟著主幹的最新進度

主幹開發的團隊經常會從主幹同步程式碼到個人電腦。事實上,他們一天可能要做好幾次這樣的動作。

在本地執行建置

採用主幹開發的開發者在提交或推送之前會先執行建置,以確保不會造成建置失敗。

這項做法對於非常小的團隊來說,可以讓他們在稍後才設置持續整合伺服器。如果因為有人早先一步提交,而無法將提交推送到主幹,那麼他們就必須再次從主幹同步程式碼到個人電腦,然後重新建置並推送修訂後的提交。

「這在我的電腦上是正常的」,這是那些不想承認自己搞砸建置的開發者的說法(假設建置是快速可靠且冪等的)。

便於提交

因為團隊中的每個人都在追蹤主幹的最新版本,所以可能會出現其中一個變更會以某種方式給其他人帶來不便。比如說,作為程式碼大規模重構的一部分,包含進行一個大規模目錄重命名。這種情況下,執行該任務的開發者可能會先進行重新命名,並將其推送到主幹,這樣所有人都會在下一次同步程式碼時獲得這些變更。如果分開進行,單獨執行重新命名可以更容易被團隊成員接受,而後續的小改動則可以稍後提交。

Git 和 Mercurial 通過文件的內容而不是目錄和文件名來追蹤文件,因此它們在上述情況下可以輕鬆應對。

克服壞掉的建置

偶爾會在主幹上觀察到建置壞掉的情況,可能是因為某個懶惰的開發者,或純粹的時間巧合(Google 每 30 秒向其單一版本庫提交一次變更——必定有 0.0001% 的提交呈現量子糾纏2的狀態)。

最佳的實踐方法是對於落入主幹的破壞性提交進行自動回滾。開發者會收到通知,然後在其個人電腦上默默修復。

想要從主幹同步程式碼的開發者,常常面臨遇到那些統計上不太可能的破壞性建置風險。如果他們正在進行開發,他們不會希望自己的個人電腦上有導致主幹破壞的提交。因此,他們會將程式碼同步到上一個已知的正確提交,並且只有在主幹上的建置正式修復後才繼續前進。這樣他們就知道自己的個人電腦上可以保持「綠燈」狀態。一些公司會設計一個系統,將上一個已知的正確提交的雜湊值或編號儲存在網路共享中,並且用於同步程式碼的 shell 腳本會使用這個值,而不是 HEAD 版本。

建置監督員

如果持續整合伺服器在每次建置中將提交批次推送到主幹,或者建置所需的時間很長,團隊內可能需要一個「建置監督員」角色來幫助解決建置失敗的問題。不幸的是,這意味著可能需要鎖定主幹,以防止在破壞的提交之上進行進一步的檢查,並且需要進行某種形式的二分法來找出哪個提交導致了建置失敗並應該回滾。顯然,能夠每次提交運行一次建置的持續整合伺服器設置是最好的。

無共享依賴

開發者在他們的個人電腦上依賴一個專為他們正在開發的應用程式或服務設置的「微觀」環境。他們可以:

  • 在他們的個人電腦上啟動應用程式並與之互動。
  • 在本地運行所有單元測試、整合測試和功能測試。

無共享外部依賴需要相當嚴格的紀律才能實現。通常意味著開發者的電腦不會通過 TCP-IP 連接外部網路,並且可以通過在離線狀態下運行這些操作來證明這一點。實現對外部團隊的依賴層進行線上模擬(service virtualization)是必要的。最成功的主幹開發團隊在同一應用程式內部使用模擬層,以使測試快速且穩定。Mountebank 等技術使得與線上模擬相關的程式設計變得容易。當然,層級指的是應用程式結構的層級結構。

採用微觀環境策略為開發者的個人電腦提供不需共享外部依賴的開發環境,意味著產品的非功能性需求會被拋在一旁,只有功能正確性才會被重視。這種作法主要適用於個人電腦上的開發活動,以及持續整合常駐程式對每次提交進行的驗證。

你的團隊將需要許多具名的 QA 環境和許多具名的使用者驗收測試(UAT)環境。每個環境都有不同的部署頻率規則,甚至可能有不同的原因暫時保留。這些環境整合了真實的依賴服務和整合應用程式。盡可能避免這些環境共享服務。

企業在購買軟體時往往犯了一個典型的錯誤,比如在正式環境購買一個許可證,而在所有開發、QA 和 UAT 環境購買另一個許可證,這意味著 DevOps 團隊將其配置為所有這些環境的共享資源,對生產力和品質產生了廣泛且多種微妙的負面影響。

共同的程式碼所有權

一天多次向主幹提交變更需要對程式碼有廣泛的所有權感,以及願意讓開發者對他們之前未涉及的應用程式或服務部分進行變更的意願。這種特權是伴隨著責任和檢查的。責任意味著程式碼必須符合標準,而檢查的部分是由持續整合伺服器,以及那些負責快速審查程式碼的人進行。最後,對於表現最好的團隊來說,這意味著一但提交準備就緒,就應立即進行審查。

永遠準備好發布

實行主幹開發的開發者不僅不會因為任何提交而導致建置失敗,他們還願意隨時準備上線。例如,如果資訊長(CIO)來訪並表示立即上線,他們可以在一小時內準備就緒。這意味著建置包含了一系列的自動化測試。

細小的垂直切片

在可能的情況下,從待辦事項清單中提取的任務或故事,應該在短時間內由一位開發者或一對開發者完成,並且只需提交少量的變更。這些任務還應該跨越整個軟體堆疊的各個層次,而不需要依賴具有專業知識的開發者才能完成。敏捷行業提供了 INVEST 原則以及「細小的垂直切片」 的概念,這些是促進高產能提交到主幹並始終保持發布準備就緒的重要推動者。


  1. 目標位置也就是版本控制系統中的分支或程式碼版本庫。 ↩︎

  2. 在這裡是一個比喻,用來描述在大型程式碼本板庫中,由於提交次數頻繁,不同開發者的程式碼變更可能會同時進行,導致一些不可預測的問題。這種現象被比喻為量子糾纏,以突顯其複雜性和不可預測性。 ↩︎