怎麼提高程式碼質量?-來自Google的研發經驗總結

小爭哥發表於2019-03-13

關注我的微信公眾號:小爭哥,獲取更多、更新的技術、非技術分享。
作者:前Google工程師,5萬人訂閱《資料結構和演算法之美》專欄作者。
希望通過我加速你的技術、職場進步。

你的團隊有沒有過這樣的經歷:開發效率低,招了很多人,天天加班,出活卻不多,線上bug頻發,領導發飆,中層束手無策,工程師抱怨不斷,查詢bug困難。其實這些都是程式碼質量差惹的禍。程式碼質量是研發質量管理的根本,它決定了整個開發團隊的開發效率,專案質量,其他監控,告警,日誌等手段都只能是事後補償。本文就如何保證程式碼質量總結了一些經驗和方法,供大家參考。

程式碼質量本身並沒有一個特別明確的量化指標,而且根據公司發展的不同階段,團隊規模的大小不同,專案性質的不同等,對程式碼質量的要求也不盡相同.不過如果專案中出現以下情況時候,就說明程式碼質量要值得重視了.

  • 新增或修改一個簡單功能時,涉及要修改的地方特別多,而且很分散;
  • 程式碼不可複用:相似的功能無法複用程式碼,要重新開發;
  • 線上bug頻發,排錯困難,修復難度大,時間長;
  • 有很多奇怪的程式碼,程式碼讀不懂,新人無法很快了解程式碼;
  • 程式碼中坑特別多,不敢大動,一不小心就踩坑;

    以上這些問題,基本上都是程式碼質量不高導致的,包括程式碼無註釋,無文件,命名差,專案層次結構差,呼叫關係混亂,到處hardcode,臨時解決方案等等。怎麼才能時刻保證程式碼的高質量,避免以上問題發生?當然團隊的技術素質很重要,除此之外,還有一些方法可循的.

    1. 吹毛求疵般地執行編碼規範

    嚴格執行程式碼編寫規範,可以使一個專案乃至一個公司的程式碼具有完全統一的風格,就像同一個人編寫的一樣,而且命名良好的變數,函式,類和註釋,也無疑可以提高程式碼的可讀性.具體落實到執行層面,可以參照Google的編碼規範或者java官方的編碼規範,網上可以找到,關鍵是要嚴格遵守,並且在code review時,嚴格要求,沒有按照規範的一定要指出並且要求修改.

    實際情況往往是雖然大家都知道優秀的程式碼規範是怎樣的,但在具體寫程式碼的過程中,卻執行的差強人意,很多情況是認識上不夠重視,覺得一個變數或者函式的命名成哪樣關係不大,所以不夠推敲,註釋很多也都不寫,code review的時候大家也都事不關己心態,或者覺得沒必要太摳細節,導致慢慢的整個code base變得越來越差.所以這裡還是要強調一下,細節決定成敗,提高團隊對程式碼規範的認同及其嚴格的執行是關鍵.

    2. 編寫高質量的單元測試

    單元測試是最容易執行,且對提高程式碼質量見效最快的方法之一還。但還是有很多公司對單元測試重視不夠,包括一些大的網際網路公司,不寫或者隨便寫寫。

    有些工程師覺得有測試團隊就夠了,再寫單元測試就是浪費時間。其實測試團隊的測試和單元測試是在不同層面上的,測試團隊的測試一般是黑盒測試,系統層面的整合測試,對於複雜系統來說,組合爆炸,測試團隊無法窮舉所有的測試用例。單元測試是程式碼層面的測試,一般是針對類的測試。既然無法從系統的整體上保證100%符合我們的預期,那單元測試起碼能保證我們程式碼在細粒度上執行符合預期。

    有些工程師認為開發任務重沒時間寫。這個還是沒有足夠重視單元測試,覺得是可有可無的部分,才會有這樣的想法。寫好單元測試,節省很多解決線上bug的時間,開發時間反而更充足了。

    還有很多工程師雖然在寫單元測試,但只對正常流程做測試。程式碼中的bug多數是寫程式碼時異常情況沒有考慮全面導致的,正常流程一般不會出問題。單元測試的作用就在於測試各種異常情況下程式碼的執行是否符合預期,所以只對正常流程測試無法發揮單元測試真正的作用。

    一般情況下,單元測試程式碼量要比要測試的程式碼多,一般是1-2倍的樣子,寫單元測試本身沒有太多的技術挑戰,主要看工程師邏輯是否縝密,能夠考慮各種異常情況,寫起來比較枯燥,所以寫高質量的單元測試的一方面要靠工程師的耐心執行,另一方面要靠團隊的嚴格要求。當然這些都是建立在對單元測試重要性的認同之上。

    3. 不流於形式的Code Review

    如果說單元測試很多工程師不怎麼重視,那code review就是不怎麼接受.跟很多大型網際網路公司的人聊過,對code review都不怎麼認可,大部分反應都是,這玩意不可能很好的執行,浪費時間,是的,code review做的再流暢,也是要花時間的,關鍵在於我們是願意花2天寫程式碼花5天修bug,還是願意花3天寫程式碼花半天修bug.

    其實,code review的好處不僅僅是能夠大大提高程式碼質量,減少程式碼bug,你想想如果我們沒有code review,平時寫的程式碼“偷偷”就commit了,難免有人不自律,有了code review,直播程式碼,曝光dirty code,大家就會更認真些.其次來講,code review也是一種有效技術傳幫帶的途徑,每次code review都是一次案例的剖析,可以幫助初級的工程師培養編碼規範,提高編碼質量,設計能力甚至於架構能力,反過來,review別人寫的好的程式碼,對自己也是一種學習和提高.

    除此之外,嚴格的code review不僅能保證程式碼的質量,還能形成良好的技術氛圍。

    4. 開發未動文件先行

    編寫技術文件對大部分工程師來說都是挺反感的事情。一般來講在開發某個系統或者重要模組或者功能之前需要先寫技術文件,然後傳送給同組或者相關同事審查,在審查沒有問題的情況下再開發,這樣能夠事先達成共識,開發出來的東西不至於走樣,而且當開發完成之後進行code review的階段,程式碼審查者通過閱讀開發文件也可以快速的理解程式碼.

    除此之外,文件對於團隊和公司來講都是重要的財富,對於新人加入公司熟悉程式碼,產品,對於任務的交接等等都很有幫助,而且作為一個規範化的技術團隊,技術文件是一種摒棄作坊式開發和個人英雄主義的有效方法,是保證團隊有效協作的途徑.

    不過,有很多工程師提出說不會寫技術文件,不知道寫什麼,希望給一個模板或者目錄.我之前曾經想過是否可以給出一個固定的模板,但最後還是放棄了,比較難,難點在於,每個專案側重點都不一樣不容易總結,如果硬要給出一個很寬泛的目錄,不具有指導性也沒有意義.大體上來講,文件的內容主要是將做的東西講清楚,包括出問題背景,解決了什麼問題,外部怎麼用或呼叫,內部如何實現,大的架構,關鍵功能和演算法等,以及一些非功能性的考慮。

    5. 持續重構,重構,重構

    個人比較反對平時不注重程式碼質量,堆砌爛程式碼,實在維護不了了就大刀闊斧的重構甚至重寫。有時候專案程式碼太多了,重構很難做到徹底,最後又搞出來一個四不像的怪物,更麻煩了!

    優秀的程式碼或架構不是一開始就能完全設計好的,就像優秀的公司或產品也都是迭代出來的一樣的,我們無法100%遇見未來的需求,也沒有足夠的精力,時間,資源為遙遠的未來買單,所以隨著系統的演進,重構程式碼也是不可避免的,雖然上面說了不支援大刀闊斧推到重來式的大重構,但持續的小重構還是比較推崇的,也是時刻保證程式碼質量防止程式碼腐化有效手段.簡單一句話就是不要等到問題堆得太多了再採取重構,要時刻有人對程式碼整體負責任,平時沒事就改改程式碼,而不要覺得重構程式碼就是浪費時間,不務正業!

    特別是一些業務開發團隊,有時候為了快速完成一個產品或者業務功能,只追求速度,到處hard code,在完全不考慮非功能性需求的情況下,堆砌一些爛程式碼,這種情況還是比較常見的。不過沒關係,等有時間一定要記著重構,不然爛程式碼越堆越多,總有一天會沒人能維護。

    6. 專案與團隊”微服務化”

    只有小專案是可以維護的,大專案是無法維護的.團隊人比較少的時候,十幾個人的樣子,程式碼量也不多,不超過10萬行,怎麼開發,怎麼管理都沒問題,大家互相都瞭解彼此做的東西,程式碼質量太差了,大不了重寫一遍.但如果是一個極其龐大的專案,幾十萬行程式碼,幾十個開發維護,那基本上沒人能對程式碼負責了.

    所以當專案太大了之後,就需要對程式碼和團隊進行拆分,模組化,大團隊拆成幾個小團隊,大專案拆成幾個小專案,這樣每個團隊每個專案的程式碼都不至於很多,也不至於出現程式碼質量太差無法維護的情況,其實很多技術也都體現了這種思想,比如大到soa, 微服務,小到jar, .so等lib模組開發,Class類的封裝,都是一種拆分的思想.

    7. 重視程式碼關注細節

    以上其他的所有方法都是治標不治本,找到對的人用好對的人,打造優秀的技術文化,才是能一直卓越的根本。有很多工程師比較熱衷於學習架構,工具,框架層面的東西,見過很多工程師,還沒寫三五年程式碼就轉做架構師,不寫程式碼了,到處忽悠,很不好,網際網路資訊如此透明,不同的人去做同一個專案,其實最後設計出來的架構,功能大約都差不多,最後大家都能把這個系統實現,但有些人做出來的系統,bug很多,效能很差,擴充套件性也不好,最多能叫個POC。

    高手之間的競爭還是在於細節,一個演算法夠不夠優化,資料存取的效率高不高,記憶體是否夠節省等等,這是累積起來決定了一個系統是不是夠優秀。

    當然並不是說框架,工具,架構設計這些方面的學習不重要,關鍵是有深度,希望是實踐中鍛鍊得來的,而不是到處看微信公眾號,部落格得來的。

    國內工程師普遍深度不夠,做幾年技術就轉管理或者純架構設計不寫程式碼了,而國外不一樣,大齡碼農很多,所以國外的優秀開源專案比較多,而國內很少。

    8. 工欲善其事必先利其器

    程式碼中的很多低階質量問題不需要人工去審查,java開發有很多現成的工具可以使用,比如:checkstyle,findbugs, pmd, jacaco, sonar等。

    Checkstyle,findbugs,pmd是靜態程式碼分析工具,通過分析原始碼或者位元組碼,找出程式碼的缺陷,比如引數不匹配,有歧義的巢狀語句,錯誤的遞迴,非法計算,可能出現的空指標引用等等。三者都可以整合到gradle等構建工具中。

    Jacoco是一種單元測試覆蓋率統計工具,也可以整合到gradle等構建工具中,可以生成漂亮的測試覆蓋率統計報表,同時Eclipse提供了外掛可以EclEmma可以直觀的在IDE中檢視單元測試的覆蓋情況。

    Sonar Sonar 是一個用於程式碼質量管理的平臺。可以在一個統一的平臺上顯示管理靜態分析,單元測試覆蓋率等質量報告。

    最後,總結

    以上所有的這些方法論應該都沒啥新奇的,也沒有葵花寶典似的殺手鐗,說出來感覺都很簡單的,現在網際網路這麼發達,資訊都很透明,所以大方向大家都知道,具體的策略和架構各家也都差不多,最後誰做的好,關鍵在於執行和細節,經常聽到有人說我們做了單元測試啊,我們做了效能測試,可最後還是一堆效能問題一堆bug,那就要去考慮一下到底做的夠不夠好,是否做到了具體問題具體分析,不生搬硬套,從決策到執行再到考核是否形成了閉環,很多時候只是空喊口號,口號喊得100分,落實到執行只能得50分,最後又完全沒考核,好壞大家也都不知,切記敏於言而訥於行。

  • 相關文章