建立持續整合程序。加速回饋循環。更新簽入程序。
書名:軟體構築美學
作者:Kyle Baley,Donald Belcham
譯者:蔡煥麟,張簡才祿
發行公司:悅知文化,精誠資訊股份有限公司
所有軟體專案都會經常碰到的問題:整合(integration)。
持續整合(continuous integration:CI)開發流程包括定期整合程式碼的工作,
便能夠即早發現應用程式的問題。
問題描述
等到最後一刻才把專案的各個模組整合起來,導致整合時出現很多錯誤。
什麼是持續整合?
持續整合是一種軟體開發實務作法,此法強調團隊成員應該經常整合彼此的工作成果,
而且是每天只少一次,即一天可以進行多次整合。
每次整合都會透過自動化建置(包含測試)來驗證,以便盡快找出整合的錯誤。
許多團隊發現這樣的方式能夠大幅減少整合問題,並且讓團隊更快開發出更強固的軟體。 - Marin Fowler
關鍵在於自動化建置:每當有人將程式碼簽入時,自動觸發建置流程。
文化轉移
導入 CI 食物的真正挑戰在於公司文化,而非技術。
可能會由於 CI 非常頻繁回報問題而招致反彈。
CI 並沒有找出比較多問題,它只是能更快找到現有問題。
導入 CI 最重要的原因就是希望能夠更快發現問題,稱之為『加速回饋循環』(closing feedback loop)
回饋循環
結合自動化測試和程式碼度量,CI就會變成非常強大的工具。
讓用戶發現錯誤是很糟糕的事情,在測試期間就找到問嚴重問題,你會慶幸還好發現得早。
加速回饋循環
開發團隊 -> 持續整合伺服器 -> 測試團隊 -> 用戶
每當問題或 Bug 溜過專案生命週期的各個階段,解決問題的成本就會急速成長。
CI則是專案團隊用來加速回饋循環的一種方式。
CI會影響整個開發流程的運作方式,讓問題能夠盡快解決。
自動化建置與建置伺服器
建置流程自動化,包括編譯、測試,和發行。
一台獨立的機器當作建置(或整合)伺服器,這台機器的組態必須盡量和用戶的正式作業環境相同,且要安裝自動化建置所需的軟體。
能夠順利運行於建置伺服器,才能確認應用程序沒有問題。
不要讓建置伺服器拖慢開發工作,虛擬化技術仍是作為專屬伺服器的可行(而且通常是最佳的)替代方案。
更新簽入程序
必須等到建置伺服器能成功編譯和測試應用程式,你才能確定一切沒問題。
建置失敗
建置失敗有三項重要的規則要遵守
1. 當建置失敗時,所有人都不能再簽入程式碼,除非是為了修正建置的錯誤。
2. 當建置失敗時,所有人都應該執行取得最新版本的動作。
3. 誰造成問題,誰就要負責修正。
CI程序是要讓開發人員在自己機器上編譯和測試程式的方式跟建置伺服器一樣。
如果開發時的編譯或測試方式跟建置伺服器不同,建置伺服器可能出現一些開發時沒有發生的錯誤。
解除痛苦:走一遍簽入流程
已經有了自動化建置程序,只要有人簽入程式碼,就會自動執行以下動作
1. 取得最新版本。
2. 編譯程式碼。
3. 透過電子郵件通知團隊這次的建置結果。
一旦自動編譯程式碼發生錯誤,就會發信給團隊成員,你也可以設定信件內文,顯示最後一次簽入的人是誰。
問題發生之後幾乎立即就會被發現,因而迅速獲得解決,這就是CI的威力。
CI與團隊互動
如果沒有CI,某個人的疏忽可能要等到下一個人處理某項工作時才會發,也許那個人會埋怨一下,但還是默默解決問題,
但真正導致錯誤的人不知道有這個問題,又或許冷冷地說一句:『你的程式碼有問題』,
無論哪一種情況都會對團隊成員產生不好的影響。
導入 CI,會通知團隊問題發生了,並且指出是誰造成的,
如果問題不常發生,而且犯錯的人並不會把別人的嘲弄放在心上,這樣的互動就是良性的。
隨著問題獲得立即修正,團隊成員也同時再度緊密地結合在一起。
節拍器效應(the metronome effect)
CI與簽入程序的一個主要優點,是它能夠讓團隊的程式開發節奏更加順暢。
專案的節奏基本上由簽入程式碼的頻率來決定,簽入多,頻率高,專案節奏自然就快。
導入CI,每一次的簽入失敗等於提醒你有問題囉,請馬上解決。
導入CI,每一次的簽入成功等於再次提醒你,專案仍處於穩定的狀態。
這種立即回饋,會進一步增強了我們對程式碼的信心。
什麼是可用的程式碼?
worked 程式碼:傳統上指的是完成了一項用戶看得到、能夠真正使用的功能。
對於開發人員來說,只要程式碼達到你原先設定的目標,他們就是可用的。
建立CI程序
自動化建置的三個基本步驟。每個步驟都是以前一個步驟的基礎。
三個步驟最好循序漸進,不要全部一次到位,以免產生太大的衝擊。
編譯應用程式
當你在處理不同組建的編譯動作時,最好能夠自動設定那些檔案的版本。
自動產生 AssemblyInfo 檔案可以讓你的CI和建置程序為組件指定版本編號。
你的CI程序就不只能編譯程式,還可以指定應用程式的版本。
執行自動化測試
包含單元測試與整合測試
建立可部署的發行
能夠隨時建立應用程式的發行套件。
發行指的是進行部署時所交付的東西。
部署則是將發行安裝到某個作業環境的動作。
CI的一個好處,就是無論目前處於專案生命週期的哪個階段,隨時都可以導入CI。
導入CI只不過是把團隊的一些日常工作加以自動化而已。
建置所需的相關檔案
與建置相關的檔案(建置腳本,組態範本等等)都必須納入版本控管。
可以在Visual Studio 方案中建立一個專案或方案資料夾來存放這些檔案。
建立一個 compile 資料夾,用來存放編譯結果。
建立一個 release 資料夾,將可部署的發行版本在這個資料夾。
compile 與 release 都不應該加入版本控管。
compile 可以隨時動態建立,所以不需要納入版控。
release 確實應該要保存起來,但建議透過夜間的備份排程,而不是版控。
調整CI程序
只要開發過程中有一些變動,就可能要重新檢視並調整建置程序。
處理長時間執行的測試
若整個測試的執行時間要花上好幾分鐘,就不能期待開發人員還坐在那兒等測試跑完才動作。
要克服長時間執行的測試所引發的問題,一種方法是將建置程序分成兩個部分
第一部分負責編譯應用程式、執行單元測試,以及建立軟體的發行版本。這項作業要在短時間完成。
第二部分類似第一部份,只是再加上執行長時間的測試。
當開發人員簽入程式碼後,執行第一個快速建置的版本,在觸發第二部分的長時間建置版本。
這樣就不用等整合測試全部執行完畢,因為一旦順利通過編譯和單元測試,就有足夠信心處理下一個工作。
架構的變動
專案的架構變動,你的部屬和發行程序也必須跟著修改。
一份結構良好的建置腳本很重要,各種變動都應該能夠輕易套用。
為建置加上標籤
為每次建置加上標籤(label)或標記(tag)。
總結
CI持續整合,它能夠協助團隊建立信心,讓團隊更加信任簽入版控系統的程式碼能夠正常運作。
CI的核心實作可以非常簡單,不用急得一次到位,只要每次進步一點,就能產生極大的報酬。