為什麼我們迫切需要持續整合(Continuous Integration)
持續整合(Continuous Integration),也就是我們經常說的 CI,是現代軟體開發技術的基礎。本文論述了當前軟體開發過程中存在的問題,講解了持續整合、持續整合伺服器的概念,最終探討了為什麼我們需要持續整合來解決這些問題。
當前軟體開發過程存在的問題
在沒有應用持續整合之前,傳統的開發模式是這樣的:
- 專案一開始是先劃分好模組,分配模組給相應的開發人員;
- 開發人員開發好一個模組就進行單元測試;
- 等所有的模組都開發完成之後,由專案經理對所有程式碼進行整合;
- 整合後的專案由專案經理部署到測試伺服器上,被交由測試人員進行整合測試;
- 測試過程中出現 Bug 就提把問題記錄進行 Bug 列表中;
- 專案經理分配 Bug 給相應的責任人進行修改;
- 修改完成後,專案經理再次對專案進行整合,並部署到測試伺服器上;
- 測試人員在下一次的整合測試中進行迴歸測試;
- 通過通過之後就部署到生產環境中;
- 如果測試不通過,則重複上述“分配 Bug -> 修改 Bug -> 整合程式碼 -> 部署到測試伺服器上 -> 整合測試”工作。
這個過程中可能會出現如下問題:
1. Bug 總是在最後才發現
隨著軟體技術的發展,軟體規模也在擴大,軟體需求越來越複雜,軟體已經不能簡單地通過劃分模組的方式來開發,往往需要在專案內部互相合作,模組之間存在一定的依賴關係,那麼早期就存在的 Bug 往往會在最後整合的時候才被發現。
2. 越到專案後期,問題越難解決
很多開發者需要在整合階段花費大量的時間來尋找 Bug 的根源,加上軟體的複雜性,問題的根源很難定位。而且我們都清楚,間隔的時間越久,Bug 修復的成本越高,因為連開發人員自己都忘了當初寫得是什麼鬼程式碼,從而不得不從頭閱讀程式碼、理解程式碼。
3. 軟體交付時機無法保障
正是因為我們無法及時修復 Bug,或者是沒能在早期就修復 Bug,從而令整個修復 Bug 的週期拉長了。不管怎麼樣,我們不可能把明知存在 Bug 的軟體交付給客戶。
而且,大量沒有在前期預估到的工作量產生了——開發人員不得不花費大把時間在查詢 Bug 上;測試人員不斷的需要進行迴歸測試;專案經理不得不疲命於該死的程式碼的整合、部署這些重複性工作——最終導致整個專案的週期拉長,交付時間點往後拖。
4. 程式經常需要變更
某些專案,程式會經常需要變更,特別是敏捷開發的實踐者。由於產品經理在與客戶交流過程中,往往實際的軟體就是最好的原型,所以軟體會被當作原型作為跟客戶交流的工具。當然,客戶最希望的當然是客戶的想法能夠馬上反映到原型上,這會導致程式會經常被修改的。那麼也就意味著“分配 Bug -> 修改 Bug -> 整合程式碼 -> 部署到測試伺服器上 -> 整合測試”工作無形又爆增了。
5. 無效的等待變多
有可能開發在等整合其他人的模組;測試人員在等待開發人員修復 Bug;產品經理在等待新版本上線好給客戶做演示;專案經理在等待其他人提交程式碼。不管怎麼樣,等待意味低效。
6. 使用者的滿足度低
這裡的使用者是廣義的,可以指最終的客戶,也可以是產品經理、公司領導、測試人員,甚至可能是開發人員自己。你想想看,本來三個月做完的專案被拉長到了九個月甚至一年,使用者能滿意嗎!產品經理、公司領導經常需要拿專案作為演示的原型,結果告訴我在演示前一刻發現還有很多 Bug 沒有解決,專案啟動不了無法訪問,這叫人情何以堪。
持續整合、持續整合伺服器的概念
那麼好了,在上面論述的這些問題中,我們發現有些工作是無法避免的,比如測試工作、修改程式、整合工作、部署工作。但其實在整個工作流程上,是存在可以優化的空間的,比如,整合測試的工作是否可以提前做?可否有自動化的手段來代替測試、整合、部署工作?圍繞這些,軟體行業的大師們提出“持續整合”口號。
1. 什麼是持續整合、持續整合伺服器
在軟體工程中,持續整合(CI)是指將所有開發者工作副本每天多次合併到主幹的做法。 Grady Booch 在1991年的 Booch method 中首次命名並提出了 CI 的概念,儘管在當時他並不主張每天多次整合。而 XP(Extreme programming,極限程式設計)採用了 CI 的概念,並提倡每天不止一次整合。
而持續整合伺服器就是能夠採用自動化的手段,來解放人的雙手,實現專案持續整合的工具。與之配套的軟體有 TeamCity、Jenkins、Go 等。
2. 怎麼樣才算是“持續”
對於一天需要整合多少次數,並沒有一個明確的定義。一般就是按照自己專案的實際需要來設定一定的頻率,少則可能幾次,多則可能達幾十次。可以設定按照程式碼的變更來觸發整合,或者設定一個固定時間週期來整合,也可以手工點選整合的按鈕來“一鍵整合”。
3. 持續整合的工作流程
- 當開始更改程式碼時,開發人員會從程式碼庫(如 SVN、Git 等)獲取當前程式碼庫的副本。
- 當其他開發人員將更改的程式碼提交到程式碼庫時,此副本將逐漸停止反映程式碼庫中的程式碼。程式碼分支保持檢出的時間越長,當開發人員分支重新整合到主線時,多個整合衝突和故障的風險就越大。
- 當開發人員向程式碼庫提交程式碼時,他們必須首先更新他們的程式碼,以反映程式碼庫中的最新更改。
- 當儲存庫與開發人員的副本不同,他們必須要花時間來先處理衝突。
持續整合的好處
1. 解放了重複性勞動
自動化部署工作可以解放了整合、測試、部署等重複性勞動,而且機器整合的頻率明顯可以比手工的高很多。
2. 更快地修復問題
由於持續整合更早的獲取變更,更早的進入測試,也就能更早的發現問題,解決問題的成本顯著下降。
3. 更快地交付成果
及早整合、及早測試減少了缺陷遺留到部署環節的機會。在某些情況下,更早地查詢錯誤還會減少解決錯誤所需的工作量。
如果整合伺服器對程式碼進行構建過程中發現錯誤,可以及時傳送郵件或者簡訊提供給開發人員進行修復。
如果整合伺服器在部署環節發現當前版本有問題不可用,整合伺服器會將部署回退到上一個版本。這樣伺服器上始終都會有一個可用的版本。
4. 減少手工的錯誤
人與機器的一個最大的區別是,在重複性動作上,人容易犯錯,而機器犯錯的機率幾乎為零。所以,當我們搭建完成整合伺服器後,以後的事就交給整合伺服器來打理吧。
5. 減少了等待時間
持續整合縮短了從開發、整合、測試、部署各個環節的時間,從而也就縮短了中間可以出現的等待時間。持續整合,意味著開發、整合、測試、部署也得以持續。
6. 更高的產品質量
整合伺服器往往提供 Code review、程式碼質量檢測等功能。對程式碼不規範或者有錯誤的地方會進行標識,也可以設定郵件、簡訊等進行告警。而開發人員通過 Code review 也可以持續提高程式設計的能力。
持續整合的最佳實踐
1. 頻繁檢出程式碼
為了讓你本地的副本和程式碼庫中的版本最小差異化,建議頻繁檢出程式碼。有時候程式碼衝突無可避免,但最小差異化最容易解決。而且,越早發現的問題,解決成本也最低。
2. 頻繁提交程式碼
這個與第1條的原理類似,頻繁提交程式碼,可以讓其他人的檢出副本和程式碼庫中的版本最小差異化。
3. 減少分支,迴歸主幹
雖然程式碼管理工具都支援分支的概念,但應儘量減少其使用。假設有多個分支並行,應及早將變更整合到主幹中,而不是同時維護軟體的多個版本。主幹作為軟體開發的工作版本。
4. 使用自動化構建
可以使用 Maven、Ant 等來實現自動化構建,這些工具可以幫助你在構建過程中實現自動化測試。前提是你有寫單元測試用例,比如 JUnit 等。
5. 提交自測
在提交工作之前,每個程式設計師必須本地整合所有的程式碼,做一個完整的構建和執行,並通過所有單元測試。這樣就減少了整合測試在整合伺服器上構建失敗的風險。
6. 當前狀態對於每個人都可見
整合伺服器在持續整合過程中發現問題,應能傳送告警給相關的干係人。同時,也可以在牆上等醒目的位置設定一個大屏顯示器,將整合伺服器的狀態實時展現在大屏上,方便提醒組員“趕緊回去解決問題”!
持續整合可能會面臨的挑戰
1. 團隊人員思想上的抵觸
- 無法接受新事物:不管怎麼樣,求穩心態的人還是多。總是有人認為老的技術代表穩定,新的事物往往會帶來問題。
- 認為手工整合也沒有多少工作量:不是所有的人都參與到了整個持續整合的環節,所以沒有辦法認識到問題全貌。
針對這個問題,可以通過設定一定的持續整合技術培訓、宣講得到改觀。
2. 管理層的抵觸
- 培訓持續整合需要投入資金啊,沒錢。
- 持續整合伺服器要增加軟硬體成本啊,沒錢。
- 開發人員領了那麼高的工資,多幹活多加班應該啊。
針對這一點,可以從開發人員的成本和持續整合的投入(軟硬體)的成本上兩者做下估算。
3. 生產環境的複雜
- 比如部署的生成環境是在政務外網,無法從網際網路直接訪問等。
目前,這個是最麻煩的,還在研究中。初步設想是讓政務外網開闢一個白名單,給持續整合伺服器設定一個單獨的通道。只是思路,未驗證。
當然,考慮到目前的工作的實際,可以先持續部署軟體到自己公司的演示伺服器上,這樣,起碼先解決了客戶和產品經理溝通所使用的原型問題。 畢竟,客戶真實使用的軟體在更新的頻率上可以適度的放寬。
參考資料
- Grady Booch. Object-Oriented Design with Applications.Benjamin Cummings,1991,3(5):209
- Paul M. Duvall,Steve Matyas,Andrew Glover.Continuous Integration:Improving Software Quality and Reducing Risk.Upper Saddle River:Addison-Wesley,2007