簡單的好習慣,是 CI 的一大步
前四天跟大家聊很多觀念與思考一些議題,今天要來聊聊 CI 該怎麼開始了!
頻繁驗證
要開始 CI 並不難,最簡單的方向:只要每次修改程式到一個段落都做驗證,這樣就是 CI 了。Day 02 介紹 CI 有提到,CI 很像對程式做健康檢查。當健康檢查越頻繁的時候,就越容易知道病源在哪裡。比方說:昨天健檢身體很健康,今天突然發現腸胃有點毛病,這時可能會懷疑昨天晚上吃燒烤的味道好像怪怪的,但絕對不會懷疑前天吃的火鍋不新鮮。
是的,這就是頻繁驗證最大的好處:縮小並聚焦問題可能發生的範圍。很多寫程式的老手都會不自覺使用這個方法在除錯。比方說下面這段程式碼:
|
在執行 foo()
的回傳值或過程不正確。這時也不知道該懷疑 foo()
還是 bar()
,所以最快的做法就是在 bar()
上面加一行 code:
var_dump($paramBar); |
接著再跑一次,確認 $paramBar
值是對的後,再加一行:
var_dump($paramBar); |
確認 $val
值沒錯後,好了,可以確定是 foo()
後續處理的問題了!這正是頻繁驗證的一種。
完整地驗證
大家可能會想說,上面這招只要是有經驗的都會知道,還輪得到我講嗎?確實,也許大家都很常用,但只有單純做頻繁驗證的話,會有一個魔鬼細節:驗證範圍。以上面程式碼和驗證方法為例,它只能驗證在同一個 $paramFoo
下,bar()
與 foo()
是正確的。但這個程式碼應該還要驗證:
- 不同的
$paramFoo
也會如預期輸出嗎? - 不合法的
$paramFoo
也會如預期丟例外嗎? - 其他呼叫
foo()
的程式都全都有如預期執行嗎?
前兩點還好,改個參數丟一下,結果還算很快就出來了。第三個該怎麼辦,還要全域搜尋所有程式去一個一個驗證,正常人應該都會受不了,就跟要求要天天去全面性健康檢查,不管是誰都無法接受。
咦?我們的目的是要一直不斷做同樣的檢查,這不正是電腦所擅長的事嗎?所以我們可以寫測試程式來驗證程式是否正確,並讓電腦幫我們驗證,這就是「自動化測試」。當每次驗證的範圍都夠大的話,就可以確保程式在這個範圍下會如預期執行了。
記錄結果
當有了自動化,相信做驗證對任何開發人員來說都不難。但要記得,每次的驗證結果都應該要被記錄下來,供未來參考。可以回想上面頻繁驗證的例子,我們也是先驗證 bar()
功能正確,再依此結果去推論 foo()
是有問題的,因此記錄結果是有必要的。
要開始記錄前,必須要有一個系統可以做程式碼開發的歷程回顧。是的,就是 Version Control System,也稱為原始碼版本控制系統,通常簡稱為「版控系統」或直接叫「版控」。這部分的實作有很多選擇,如 Subversion、Git、Mercurial 等。使用版控系統的好處很多,當然最大的好處在資訊分享:可讓團隊成員取得軟體的原始碼、自動化程式碼和開發歷程。
那什麼時候該記錄驗證結果呢?其實答案也是呼之欲出:當提交程式碼到版控系統時,就能記錄了。版控系統的提交資訊也可以結合驗證結果的資訊,並分享給團隊成員,讓大家可以避免拿到驗證失敗的程式碼,同時也能取得足夠的資訊繼續開發。目前常見的 SaaS 版控系統都有做這一類的服務,如下圖是 GitHub + GitBook 的範例。
正確才能提交
Day 04 提到了「先要對,才會有」。而對工程師而言,程式碼要先驗證通過,才能提交程式碼進版控系統,這時就可以跟團隊成員說功能已經「有」了。
相反地,提交驗證不通過的程式碼,是在把 bug 分享給團隊成員。而其他人修改程式發生問題時,也很難去鎖定問題的範圍。比方說上例程式,如果不知道 bar()
是不是對的,就無法確定 foo()
是否有問題。對除錯來說,只要有越多的疑惑,障礙就越大。但只要養成良好習慣:驗證通過,才提交程式碼,這樣就能更有效率的開發,同時也避免風險擴大。
有錯立即修正
人並不完美,自動化是人寫的,或多或少會遺漏必要的驗證。如果已經知道取得的程式碼有問題了,最好的決策就是立即修復它,而不要在知道有問題的狀況下加新功能,因為這很有可能會讓 bug 擴散到新功能裡。
另外,還有一個重要理由是,只要團隊接受程式有任何小錯誤,接著可能會有人開始提交錯誤程式碼,反正有人會接受嘛!最終就會像破窗效應所說的,整個團隊會開始不在乎程式是否有錯。當這個文化被建立時,要做到頻繁驗證就會是天方夜譚了。唯有強迫團隊對任何錯誤都視為優先解決目標,才有辦法建立起良好的 CI 文化。
自己的程式自己驗
原始碼要包含所有能讓開發者可以自己執行驗證的資訊,如使用套件或驗證腳本等。主要是因為:要能讓開發者自行確認程式是否正確,並方便地在自己開發主機上做頻繁驗證。除此之外,另一個原因是要能讓程式碼在不同的地方都能執行驗證,如新進成員的電腦、或是 CI Server,甚至是產品上線環境裡等。
常常提交與更新程式碼
上面已經提到很多有關驗證除錯的好習慣。最後,就是要養成常常提交與更新程式碼的習慣了!這背後有很多重要的原因:
- 因為要正確才能提交,所以常常提交的另一個含意就是頻繁驗證。
- 有錯立即修正有提到自動化驗證也有可能遺漏,如果不常提交程式的話,問題的範圍可能會非常大,難以偵錯。
- Day 02 有提到 CI 要整合程式碼與環境。除此之外最重要的,就是要整合團隊成員們的程式碼。同樣地,常提交並更新做程式碼整合的話,就算有問題也只會是小問題。
參考書籍
前面提到的一些要領,是參考自 CI 的經典名著--Continuous Integration 並用個人想法表達出來的,原文裡面有提到開發人員所要遵守的七大要領:
- Commit code frequently
- Don’t commit broken code
- Fix broken builds immediately
- Write automated developers tests
- All tests and inspections must pass
- Run private builds
- Avoid getting broken code
有興趣的話,可以翻這本書了解原作的想法與細節。
今日回顧
- CI 先從頻繁驗證做起,且驗證要夠全面才會有效。
- 常常提交驗證成功的程式碼給團隊成員,盡量不要讓衝突太多以致無法解決。
- 大數據正夯,驗證完記錄結果也是一定要的!
- 驗證正確,就能提交程式碼!驗證失敗,就要立馬改!
- Bug 最愛躲在不常健檢的團隊裡了,而 CI 就是要團隊用盡各種方法讓 bug 躲不下去!
當然,驗證不能只是說說,團隊必須要決定驗證什麼樣內容,才有辦法做持續驗證,因此:
下一篇:CI 起步走
相關連結
- Version Control System - 維基百科
- 破窗效應 - 維基百科