1. 程式人生 > >如何保障Go語言基礎代碼質量?

如何保障Go語言基礎代碼質量?

ber 標桿 www 產品化 int 鏈路 通過 直接 負責

為什麽要談這個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

如何保障Go語言基礎代碼質量?