為什麼要談這個topic? 實踐中,質量保障體系的建設,主要針對兩個目標: 一是不斷提高目標業務測試覆蓋率,保障面向客戶的產品質量;二就是儘可能的提高人效,增強迭代效率。而構建全鏈路質量卡點就是整個體系建設的核心手段。筆者用下圖來描述這整個鏈路: 可以看到,雖然保障業務迭代的方向性正確排在最前面,但 ...
為什麼要談這個topic?
實踐中,質量保障體系的建設,主要針對兩個目標: 一是不斷提高目標業務測試覆蓋率,保障面向客戶的產品質量;二就是儘可能的提高人效,增強迭代效率。而構建全鏈路質量卡點就是整個體系建設的核心手段。筆者用下圖來描述這整個鏈路:
可以看到,雖然保障業務迭代的方向性正確排在最前面,但在具體操作上,這一步需要的是強化流程規範和構建企業文化,同時對各負責人技能培訓,可以說多數是軟技能。而保障基礎代碼質量環節發力於自動化建設鏈路之始,是可以通過技術手段來消滅潛在的質量問題,所以構建好的話能極大的降低心智負擔,非常值得關註。
我們都知道,代碼的好壞會直接影響到業務質量,團隊協作,以及後期技術債等。有一個經典的圖來描述代碼質量的好壞,當能深切表達程式員的內心:
而同時我們相信,絕大部分程式員都有追求卓越的初心,且會儘可能的在自己能力範圍內編寫高質量的代碼。
但是,保障基礎代碼質量光靠程式員的個人素質一定是不全面,是人就會犯錯,可能會疏忽。我們最需要的是一種自動化的機制來持續確保不出問題。這也是自動化的魅力,一次構建,持續收穫價值。
此類工具在業界一般叫linter,不同的語言有不同的實現。本文主要探究Go語言相關的。
在介紹相關工具之前,我們先看看幾個經典的代碼壞味道:
這段代碼常規運行不會有問題,但是在一些場景下迴圈執行,那可能就會有問題了, 我們來看看:
(註:ex2是上述代碼編譯出的可執行文件名字)
很明顯,有句柄泄露。原因也很簡單,http response的body沒有關閉。但這個關閉語句,一不註意也容易寫錯:
這時候如果百度掛了,上述程式程式就會因為空指針引用,造成非預期的panic,非常的不優雅。所以正確的做法應該是在err判斷之後再行關閉body(關於Client.Do 具體的各種限制,大家可以參考這裡: https://golang.org/pkg/net/http/#Client.Do)
如此種種,此類小問題在實際編碼活動中非常常見,且不容易一眼看出問題。甚至常規的測試可能也難檢測出來,可謂非常棘手。好在Go語言的開發者們為我們想到了這一點,內置工具鏈中的vet命令,就能方便的檢測到很多類似的問題。
還比如下麵的代碼場景,我在實際的測試用例和業務代碼都看到過:
go vet 可以很容易檢測出這個問題(其他vet功能,可以參考這裡: https://golang.org/cmd/vet/)。
go的工具鏈中,還有一個不得不提,那就是大名鼎鼎的go fmt,其了卻了其他語言經常陷入的代碼風格之爭,是Go語言生態構建非常巧妙的地方。另外golint也是google主推的go語言代碼代碼風格工具,雖非強制,但強烈建議新項目適用。
Go linters業界現狀
上面主要說到Go工具鏈的內置工具,還有一些非官方的工具也比較有名,比如 staticcheck, errcheck在github上Star都較多。此類工具有個專門的的github庫,收集的比較全,參見 awesone-static-analysis
同時還有些項目旨在聚合此類工具,提供更方便的使用方式,以及一些酷炫的產品化。比如golangci-lint, 其衍生的商業化項目,可以自動針對github PR做代碼審核,對有問題的地方自動comments,比較有意思。
如何才能優雅的落地linter檢查?
linter工具必須為產品質量服務,不然就是做無用功。實踐中,我們應該思考的是如何才能優雅的落地linter檢查,如何才能建立有效的質量卡點。
推薦針對PR,做代碼檢查,保障入庫代碼質量。基於PR做事情是我比較看好的,因為這是調動所有研發力量,天然契合的地方。且進一步講,這也是測試基礎設施更能體現價值的地方。
目前Github上有很多這方面的集成系統做的都比較好,能夠快速的幫我們落地PR測的檢查,比如Travis, Circle CI等。另外就是著名的Kubernetes社區,也自行構建了強大的Prow系統,其不光是基於CICD系統,還構建了chat ops模式,為參與Kubernetes的社區的貢獻者提供了方便。
細看Kubernetes庫,會發現,其會針對每個PR都做如下靜態檢查:
- gofmt: https://github.com/kubernetes/kubernetes/blob/master/hack/verify-gofmt.sh
- govet: https://github.com/kubernetes/kubernetes/blob/master/hack/make-rules/vet.sh
- golint: https://github.com/kubernetes/kubernetes/blob/master/hack/verify-golint.sh
因為golint只是糾正代碼風格,並不是強制,所以k8s官方就弄了比較軟的方案,對於當前已經存在的代碼如果有問題,先排除掉(如下)。對於新生代碼,如果檢查失敗,ci就掛掉。
https://github.com/kubernetes/kubernetes/blob/master/hack/.golint_failures
Kubernetes只利用了官方的幾款工具, 在檢測準確性上比較有保障。有了這些檢查點,也能倒逼研發人員關註提交代碼的質量,會迫使其在本地或者IDE上就配置好檢查,確保每次提交的PR都能通過檢查,不浪費CI資源。這也是合格工程師的基本要求。
總結
高質量的代碼是業務質量保障的基礎。而編寫高質量的代碼是技術問題,同時也應該是企業文化問題。因為當大家都開始註重技術,註重代碼質量時,自然會朝著精益求精的路上行進,視糟糕的代碼為仇寇。
我的一位老闆跟我說過,要做就做Number One。而在沒達到第一的時候,那就要向業界標桿看齊,比如Netflix,Google,Facebook等。當大家都非常註重自己代碼質量時,工程師才有時間去關註解決更加系統性的問題,而不用一直在Low Level徘徊。筆者深以為然。
Contact me?
Email: [email protected]
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi