改善 Java 代碼質(zhì)量的工具與方法
我們可能見過上面的有關(guān)代碼質(zhì)量的圖片,究竟如何衡量一段代碼好壞?
代碼質(zhì)量是什么?為什么它很重要?
作家通過他的著作來講述了一個清晰的、令人信服的故事。他們使用章節(jié)、標(biāo)題和段落等工具來清晰地組織他們的思想,并輕松地引導(dǎo)讀者。
開發(fā)者的工作與作家類似,只是使用不同術(shù)語如命名空間、類和方法。如果創(chuàng)作者不能有效地使用他們的工具,那么無論他們的作品是書還是代碼,讀者都很難讀懂。
回到代碼質(zhì)量這個話題,好的代碼都應(yīng)該具備如下一系列理想特征:
- 可靠:能夠穩(wěn)定工作,不會頻繁崩潰。
- 一致的代碼風(fēng)格:遵循該語言一致的代碼風(fēng)格和命名慣例。
- 可維護(hù):易于理解,可維護(hù)的代碼應(yīng)該易于擴(kuò)展及添加新功能。
- 完善的測試:具備良好測試的代碼往往 bug 更少。
- 高效:不應(yīng)使用不必要的資源來執(zhí)行所需的業(yè)務(wù)。
- 安全:應(yīng)防止SQL注入等編碼漏洞。
- 較低的技術(shù)債務(wù):較低的技術(shù)債務(wù)使團(tuán)隊能夠快速前行和開發(fā)新功能,而不會被低質(zhì)量和不可維護(hù)的代碼拖累。
具備的上述特征越多,代碼的質(zhì)量就越高。根據(jù)項目及客戶的具體情況,其中一些特性可能不是代碼必需的。
當(dāng)面臨交付期限時,編寫高質(zhì)量的代碼非常具有挑戰(zhàn),但如果你考慮到代碼的長期可維護(hù)性,這一點很重要。同時,高質(zhì)量的代碼也會幫助團(tuán)隊長期保持一致的交付速度。
根據(jù)我的經(jīng)驗,下面是一些在我的項目中對改進(jìn)和維護(hù)高質(zhì)量代碼非常有效的總結(jié)。
使用靜態(tài)代碼分析器提高代碼質(zhì)量
編譯器可以捕捉和防止語法問題,但它們無法檢測到類似情況:
- 代碼結(jié)構(gòu)不一致
- 社區(qū)已經(jīng)成型的經(jīng)驗
- 代碼復(fù)雜性
靜態(tài)代碼分析是一種在代碼運行前對其進(jìn)行檢查的技術(shù)。有一些工具可以進(jìn)行靜態(tài)分析,它的工作原理是根據(jù)多種編碼規(guī)則分析代碼,來發(fā)現(xiàn)一些違規(guī)行為。這些工具可以集成到構(gòu)建工具中,如 gradle、maven 等,并讓有問題的代碼構(gòu)建失敗。
以下是一些可以整合到項目中的工具。
Checkstyle
Checkstyle (1) 是開發(fā)中用于檢查 Java 源代碼是否符合編碼規(guī)則的靜態(tài)代碼分析工具。Checkstyle 進(jìn)行的檢查限于代碼的表現(xiàn)形式,這些檢查并不能確認(rèn)代碼的正確性和完整性。
https://checkstyle.sourceforge.io/
使用 Checkstyle 可以確保開發(fā)團(tuán)隊遵循一致的編碼風(fēng)格,使其更容易閱讀和理解。
下面是一些可以使用 checkstyle 進(jìn)行的檢查。
- 屬性和方法的命名慣例
- 函數(shù)參數(shù)的數(shù)量
- 代碼每行最大寬度
- 強制性的文件頭描述,如版權(quán)
- import 和范圍修飾符
- 字符之間的空格
- Class 構(gòu)建函數(shù)的約定
- 多重代碼復(fù)雜度測量
PMD
PMD(Programming Mistake Detector,編程錯誤檢測器)(1) 是一個靜態(tài)代碼分析器,它可以報告在應(yīng)用程序代碼中發(fā)現(xiàn)的問題。
https://pmd.github.io/
PMD 可以幫助檢測代碼中的問題,這些問題可能會在代碼交付生產(chǎn)環(huán)境時引起問題。
- 可能的 bug: 空的 try/catch/finally/switch 塊,吞掉原來異常并拋出一個新的異常。
- 死代碼:未使用的局部變量、參數(shù)和私有方法。
- 空的 if/while 語句
- 過于復(fù)雜的表達(dá)式: 不必要的 if 語句,for 循環(huán)可以是 while 循環(huán)。
- 次優(yōu)代碼:浪費的 String/StringBuffer 的使用
- 高循環(huán)復(fù)雜度的類
- 錯誤的 BigDecimal 用法
CPD(復(fù)制/粘貼檢測器)
CPD (1),顧名思義,是一個基于拷貝的檢測器,即使對于大型代碼庫來說也是非常高效的。它使用 Karp-Rabin (2) 字符串匹配算法編寫。
https://pmd.sourceforge.io/pmd-4.2.5/cpd.html
https://xlinux.nist.gov/dads/HTML/karpRabin.html
它可以被配置為檢測大于確定數(shù)量的標(biāo)記的重復(fù)。復(fù)制/粘貼代碼是不可取的,因為它使代碼難以維護(hù),并可能在對其中一個地方做了一些改變,而忘記在其他地方也存在相同的代碼的情況下導(dǎo)致 bug。
衡量代碼質(zhì)量
免責(zé)聲明:當(dāng)一項措施成為目標(biāo)時,它就不再是一項好措施。(1)
https://en.wikipedia.org/wiki/Goodhart%27s_law
代碼覆蓋率指標(biāo)
代碼覆蓋率是一個指標(biāo),可以用來獲得一些關(guān)于代碼質(zhì)量的信心。說了這么多,選擇哪些測試來衡量覆蓋率時要小心。并不是所有測試金字塔的測試都是一樣的,像 JaCoCo 這樣的工具可以用來計算代碼覆蓋率。
在看代碼覆蓋率的指標(biāo)時,只應(yīng)該考慮單元測試,因為單元測試是為了測試代碼是否完成了開發(fā)者想要做的事情,執(zhí)行這些測試是最快的驗證方法。
衡量集成測試的代碼覆蓋率可能是有價值的,但它應(yīng)該被視為單獨的結(jié)果,而不應(yīng)該與單元測試報告合并。記住集成測試是為了確保所有的組件一起工作。使用集成測試來提高代碼覆蓋率,就像使用大錘來敲開一個螺母一樣。
毒性圖(Toxicity Chart)
毒性圖(Toxicity Chart) (1),顧名思義是一種展示代碼毒性的方法。這個圖代表了代碼庫中每個類的毒性,毒性分?jǐn)?shù)是根據(jù)一系列參數(shù)計算出來的,比如文件長度、方法長度、循環(huán)復(fù)雜度、嵌套語句等等。這個圖表可以展示給業(yè)務(wù)人員、管理人員等非技術(shù)人員,幫助他們了解代碼的質(zhì)量。
https://erik.doernenburg.com/2008/11/how-toxic-is-your-code/
示例代碼
下面的 Github 倉庫包含了一個包含上述所有工具的示例項目。它的結(jié)構(gòu)讓你很容易選擇一些需要的工具來集成到你自己的項目中。
https://github.com/singhalkul/java-quality-checks
保持代碼質(zhì)量是一個持續(xù)的過程,它不能由團(tuán)隊中的某一個人來完成,整個團(tuán)隊都有責(zé)任確保編寫的代碼是高質(zhì)量的。
雖然上面提到的工具會幫助確保減少代碼中一些質(zhì)量問題,但這不是唯一的方法。團(tuán)隊?wèi)?yīng)該遵循極限編程實踐,如配對編程、測試驅(qū)動開發(fā)、代碼審查、持續(xù)集成,以確保高質(zhì)量代碼特征存在于代碼庫中。
英文原文:
https://medium.com/inspiredbrilliance/improving-code-quality-for-java-projects-5d24ad448109
本文轉(zhuǎn)載自微信公眾號「高可用架構(gòu)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系高可用架構(gòu)公眾號。