前幾天,參與的專案遇到緊急狀況,剛改版的系統有一段邏輯因正式台資料與預期不同而出錯,需要緊急換版,負責的同事因故無法即刻救援,改派我代打上陣。有一段時間沒參與,我對最新開發進度有點脫節,本次代打任務形同開發團隊的一次臨時抽考。
在我的開發機器開啟Visual Studio,先從TFS版控抓回最新的程式碼版本(Get Latest Version),檢視問題程式的修改歷史(View History),使用版本比對(Compare)功能找出本次修改位置,與PM確定規格後修正程式重新簽入(Check In),再利用先前設好的建置定義(Build Definition)由TFS Build Service抓取修改後程式碼編譯並部署到驗收測試環境,確認問題修復後由OP將程式上到正式台,危機解除,通過隨堂測驗!(下圖為TFS常用版控功能的示意)
任務完成後內心升起小小成就感:寫了十幾年專案,一路學習更完善的原始碼管理(雖然沒有很積極,而且多是同事主推,我拿香跟著拜 :P),終於有這麼一天-當事人不在,專案其他成員都也敢放膽修改程式上版,不擔心版本錯亂!
想到一項有趣但中肯的原始碼版本管控水準衡量指標:「你敢不敢幫請假的同事編譯專案上線?」
依我的觀點,要實現的關鍵有二:程式碼永遠只從版控取最新版本、編譯上版作業一律由自動程序執行。
前者是目標,後者為手段。每次上線建置一律由版控系統抓最新版,可避免上線程式混入某人硬碟才有的特有版本。不能精準掌握線上系統的原始碼版本,意味著不保證下次還能編譯出一模一樣的程式。「上次明明修過的Bug,換版後又冒出來」、「Bug修好了,上個月加的新功能卻消失了」… 一直是開發團隊的惡夢。
解決這個問題要從「禁止使用來路不明程式碼編譯上線」做起,任何時候,要上線的程式只能來自版控系統最新版本,只要不是從版控抓的就叫「來路不明」,防堵「要靠某人電腦D糟才能編譯正確版本」的危機。
即便所有程式碼都進版控,只要編譯過程允許人為介入,還是可能產生疏漏,因此要做到「編譯上版作業一律由自動程序負責」。人工操作常隱含陷阱,像是編譯前忘記抓最新版、編譯出錯時為求省事靠手動排除。前者會造成版本錯亂,後者讓其他人無法重新編譯出相同結果,都很惱人。要徹底解決這個問題,「人類閃開,讓機器來」-使用自動化編譯程序,程序一律由版控取回最新版編譯後再部署到測試或正式主機,不需要任何人為介入。若遇上編譯失敗或結果不正確,只能靠修改版控裡的程式碼克服。如此,才能確保任何人啟動自動編譯部署的結果都相同。
整理一些執行要點:
- 版控!版控!版控!
不管是你是用VSS、TFS或是Git/Github,都好,確認所有重要專案都有進版控,少了這一步,其餘免談。版控系統確保所有人的開發成果都被彙整妥善保管,必要時可以追溯修改軌跡,甚至能改變所有的錯,讓我從頭改過…
另外,一旦開始依賴版控,別忘了為版控系統規劃備份機制,省得天有不測風雲,所有努力化為青煙。 - 不要Check In任何還不打算上線的程式碼
程式碼一旦Check In,就會被編譯進要上線的版本,但實務上不可能等到程式全部改好測完才Check In,開發過程三不五時要Check In才好保留軌跡。針對較複雜的修改或新功能開發,可在版控切出Branch並行開發,完成後再Merge回線上版本,在Branch裡即可自由Check In/Check Out,不必擔心影響正式系統。
還有一種做法是一開始就Branch出開發版跟上線版,開發人員永遠Check In進開發版,要上線時再逐一列舉項目Merge回上線版。這種做法更嚴謹,隔離性更佳,但每次上線要詳列更動項目,手續較為繁瑣。 - 貫徹「編譯上線工作一律由機器執行」
前面提到編譯上線不交給人工處理,才能貫徹「永遠使用版控的最新版,誰來執行都得到相同結果」,也不會出現「忘記Get Latest Version」這類失誤(某中年程序員慚愧低頭 orz)。要執行自動編譯上線程序,我們過去用過CruiseControl.NET,現在則逐步改用TFS Build Service。開Visual Studio人人都會編譯,改成自動程序時要改用MSBuild,雖然不難,但仍需要花點時間學習。
當然,在軟體工程領域,這一步之後還有更美妙的境界-整合自動測試,每次編譯後先跑測試,驗證功能無誤後再上線。到此境界,不要說替同事編譯上線,就連保全大哥、茶水間阿姨、林志玲、陳妍希… 人人可以幫系統上線不擔心出亂子,很美吧!而我們離那塊流著奶與蜜之地,仍有西天取經般的距離。
有很長一段時間,每次編譯上線都提心吊膽版本錯亂,到今天進步到「膽大包天敢代替同事上程式」,能達此境界老骨頭內心已十分有感,也祝福大家早日走到這一步。