這五款牛逼的 IDEA 插件,堪稱代碼質(zhì)量檢查利器!
共 12457字,需瀏覽 25分鐘
·
2024-04-28 09:47
來源:blog.csdn.net/a745233700?type=blog
-
一、Alibaba Java Coding Guidelines -
二、CheckStyle: -
三、PMD -
四、FindBugs: -
五、SonarLint: -
總結(jié)
隨著業(yè)務(wù)的發(fā)展,系統(tǒng)會越來越龐大,原本簡單穩(wěn)定的功能,可能在不斷迭代后復(fù)雜度上升,潛在的風(fēng)險也隨之暴露,導(dǎo)致最終服務(wù)不穩(wěn)定,造成業(yè)務(wù)價值的損失。而為了減少這種情況,其中一種比較好的方式就是提高代碼質(zhì)量,比如通過代碼審查,從而降低錯誤風(fēng)險,但是,代碼審查難度大,代碼缺陷、漏洞不易發(fā)現(xiàn),且審查工作隨著代碼量增加而增加,審查效率低。
工欲善其事,必先利其器,因此,這篇文章給大家介紹幾種檢查代碼質(zhì)量的利器,Alibaba Java Coding Guidelines、CheckStyle、PMD、FindBugs、SonarLint,讓你在關(guān)注代碼質(zhì)量的同時,減少 code review 的工作量,提高 code review 的效率,并通過代碼質(zhì)量分析去反向提升我們的代碼編寫能力
一、Alibaba Java Coding Guidelines
1、整體介紹:
Alibaba Java Coding Guidelines 專注于Java代碼規(guī)范,目的是讓開發(fā)者更加方便、快速規(guī)范代碼格式。該插件在掃描代碼后,將不符合規(guī)約的代碼按 Blocker、Critical、Major 三個等級顯示出來,并且大部分可以自動修復(fù),它還基于 Inspection 機制提供了實時檢測功能,編寫代碼的同時也能快速發(fā)現(xiàn)問題所在。
阿里巴巴規(guī)約掃描包括:
-
OOP規(guī)約 -
并發(fā)處理 -
控制語句 -
命名規(guī)約 -
常量定義 -
注釋規(guī)范
2、安裝步驟:
File > Settings > Plugins > Marketplace 搜索 “Alibaba Java Coding Guidelines”,按照提示進行安裝,然后重啟即可。
3、使用說明:
3.1、運行方式:
(1)可以Tools > 阿里編碼規(guī)約 > 編碼規(guī)約掃描
(2)在編輯界面或者項目區(qū)域點擊右鍵,在右鍵菜單中選擇“編碼規(guī)約掃描”即可:
3.2、菜單功能:
-
編碼規(guī)約掃描 :開始掃描代碼 -
打開/關(guān)閉實時檢測功能 :實時檢測代碼,一般機器性能比較好的話可以開啟這項功能 -
切換語言至英文 :中英文切換
3.3、運行結(jié)果:
掃描完成后顯示結(jié)果如下,我們可以看到掃描結(jié)果主要分為 Blocker(阻擋者)、Critical(嚴重問題)、Major(主要的)三個大類,它們表示的是問題的嚴重程度,嚴重程度由高到低為:Blocker > Critical > Major,至于每一類中都會包含什么樣的問題,圖中的內(nèi)容已經(jīng)說明了一切。
選中其中的一個問題項目,會出現(xiàn)如下內(nèi)容(如果當(dāng)前鼠標點擊的是最終項,右邊區(qū)域顯示的是其它的內(nèi)容,后面會再講到):
(1)指定區(qū)域搜索同一類問題:
當(dāng)點擊③處的按鈕時,會彈出如下按鈕:
這里選擇掃描區(qū)域,來掃描鼠標選中的同類問題。如果按照默認選擇,那么運行后的結(jié)果就如下圖所示:
這里我們可以看到,顯示了整個Project中的所有該類的問題。
(2)預(yù)覽具體的不規(guī)范代碼:
如果點擊的是最終的問題點或者問題所在的類文件,那顯示的就是如下界面,預(yù)覽該處不規(guī)范的代碼。
3.4、工具欄功能介紹:
-
Rerun Inspection:重新運行一次掃描 -
Close:關(guān)閉真?zhèn)€AJCG面板 -
Expand All:展開結(jié)果的樹狀結(jié)構(gòu),整個結(jié)果是樹狀結(jié)構(gòu)的。 -
Collapse All:收起結(jié)果的樹狀結(jié)構(gòu) -
Go Pre Problem:選擇上一個問題 -
Go Next Problem:選擇下一個問題 -
Help:幫助 -
Group by Serverity:(不知道如何描述) -
Group by derectory:按目錄分組/按類名分組間切換 -
Filter resoled items:過濾掉已經(jīng)解決的項 -
Autoscroll to Source:自動滾動到源碼 -
Export:導(dǎo)出,可以導(dǎo)出為XML和HTML兩種格式 -
Edit Settings:編輯設(shè)置
二、CheckStyle:
1、整體介紹:
CheckStyle 側(cè)重檢查編碼格式和代碼風(fēng)格規(guī)范,如命名規(guī)范、Javadoc注釋規(guī)范、空格規(guī)范、size度量(如過長的方法)、重復(fù)代碼、多余Imports等,從而有效約束開發(fā)人員更好地遵循代碼編寫規(guī)范。Checkstyle主要是文法層面的代碼編寫規(guī)范的分析,對bug幾乎沒什么發(fā)現(xiàn)能力。
Checkstyle插件中默認內(nèi)置有2個執(zhí)行代碼檢查的配置文件(Sun Checks 和 Sun Checks),但是這兩個文件檢查的非常詳細嚴格,即使優(yōu)秀的開源項目也會檢查出來有非常多的錯誤告信息,所以需要導(dǎo)入我們自定義的配置文件。
2、安裝步驟:
通過 File > Settings > Plugins > Marketplace 搜索 “CheckStyle”,按照提示進行安裝,然后重啟即可。
3、使用說明:
可以看到基本都是一些縮進啥的編碼規(guī)范,可以不用太關(guān)注
三、PMD
1、整體介紹:
PMD側(cè)重面向安全編碼規(guī)則,且具備一定的數(shù)據(jù)流分析和路徑分析能力,能力比CheckStyle稍微強點,并且 PMD 支持自定義規(guī)則,PMD可以直接使用的規(guī)則包括以下內(nèi)容:
-
潛在的bug :空的 try/catch/finally/switch語句 -
未使用的代碼(Dead code) :未使用的變量、參數(shù)、私有方法等 -
可選的代碼 : String/StringBuffer的濫用 -
復(fù)雜的表達式 :不必須的if語句、可被while替代的for循環(huán) -
重復(fù)的代碼 :拷貝/粘貼代碼意味著拷貝/粘貼bugs -
循環(huán)體創(chuàng)建新對象 :盡量不要在循環(huán)體內(nèi)實例化新對象 -
資源關(guān)閉 :Connect,Result,Statement等使用之后確保關(guān)閉掉
2、安裝步驟:
通過 File > Settings > Plugins > Marketplace 搜索 “PMDPlugin”,按照提示進行安裝,然后重啟即可
3、使用說明:
-
參考文章:http://wjhsh.net/andy-songwei-p-11830812.html
3.1、運行方式:
(1)從Tools菜單中啟動:
通過 Tools > Run PMD 可以看到如下的界面,如果通過該方式啟動,掃描的范圍就是整個項目中的文件了。
-
Pre Defined :預(yù)定義的規(guī)則,也就是插件自帶的檢測規(guī)則。后面展開的列表中列出了所有的規(guī)則列表,想掃描哪一種類型的問題,點擊即可。其中“All”表示使用所有的規(guī)則。 -
Custom Rules :自定義的檢測規(guī)則,PMD允許用戶根據(jù)需要自定義檢查規(guī)則,默認這里是不可點擊的,需要在設(shè)置中導(dǎo)入自定義規(guī)則文件后方可選擇。
(2)從右鍵菜單中啟動:
在文件或者編輯器中點擊右鍵,也可以看到“Run PMD”選項,如果通過該方式啟動, 檢測范圍取決于鼠標或光標當(dāng)前所選中的區(qū)域。
3.2、運行結(jié)果:
運行后會出現(xiàn)如上所示的面板,左邊工具欄,鼠標停留在上面會提示其功能;右邊顯示了檢測結(jié)果,當(dāng)點擊具體某一問題項時,會跳轉(zhuǎn)到對應(yīng)的源碼中。
3.3、配置檢測規(guī)則:
通過 File > Settings > Other Settings > PMD 可以打開檢測規(guī)則的設(shè)置界面:
在 “RuleSets(規(guī)則設(shè)置)” 界面可以管理自定義的檢測規(guī)則。因為在實際工作中,可能需要根據(jù)實際情況自定義檢測規(guī)則,就可以通過這里導(dǎo)入,如果要使用它,需要在啟動PMD進行檢測時選擇該自定義規(guī)則。
點擊“Options”選項卡,在其中可以配置一些檢測規(guī)則選項:
其中重點需要留意的是“Skip TestSource”這一項,因為在項目中有不少Android Studio自動生成的測試代碼,如下所示,選擇上述選項后可以將其過濾掉。
四、FindBugs:
1、整體介紹:
FindBugs 側(cè)重于發(fā)現(xiàn)代碼中存在的bug,如運行時錯誤檢測(空指針檢查、未合理關(guān)閉資源、字符串相同判斷錯(==,而不是equals)等),它可以簡單高效全面地幫助我們發(fā)現(xiàn)程序代碼中存在的bug以及潛在隱患,針對各種問題,它提供了簡單的修改意見供我們參考
2、安裝步驟:
通過 File > Settings > Plugins > Marketplace 搜索 “FindBugs”,按照提示進行安裝,然后重啟即可
3、使用說明:
FindBugs 可以分析單個文件、包下面的所有文件、整個module下的文件、整個project下的文件,右鍵想要分析的文件名/包名/module名/project
分析完之后就會出現(xiàn)結(jié)果面板
點擊對應(yīng)的item在右邊會定位到具體的代碼,這是根據(jù)提示進行處理修改就行
4、附:常見的錯誤信息
4.1、Bad practice 代碼壞習(xí)慣:
| 錯誤信息 | 說明 |
|---|---|
| Class names should start with an upper case letter | 主要包括類名的命名,以大寫字母開頭 |
| Method names should start with a lower case letter | 方法名以小寫字母開頭 |
| Field names should start with a lower case letter | 字段名以小寫字母開頭 |
| equals()method does not check for null argument | equals()方法應(yīng)該檢查非空 |
| Class defines equals() and uses Object.hashCode() | 一個類重寫了equals方法,但沒有重寫hashCode方法,使用了Object對象的hashCode方法 |
| Method ignores exceptional return value | 方法忽略返回值的異常信息 |
| Equals method should not assume anything about the type of its argument | equals(Object o)方法不能對參數(shù)o的類型做任何的假設(shè)。比較此對象與指定的對象,當(dāng)且僅當(dāng)該參數(shù)不為 null,并且是表示與此對象相同的類型的對象時,結(jié)果才為 true。 |
| Comparison of String objects using == or != | 用==或者!=去比較String類型的對象 |
| Method might ignore exception | 方法可能忽略異常 |
| Method invokes System.exit() | 在方法中調(diào)用System.exit(…)語句,考慮用RuntimeException來代替 |
| Method ignores result of InputStream.read() | InputStream.read 方法忽略返回的多個字符,如果對結(jié)果沒有檢查就沒法正確處理用戶讀取少量字符請求的情況 |
4.2、Dodgy code 糟糕的代碼:
| 錯誤信息 | 說明 |
|---|---|
| Switch statement found where default case is missing | Switch沒有默認情況下執(zhí)行的case語句 |
| Switch statement found where one case falls through to the next case | Switch語句中一個分支執(zhí)行后又執(zhí)行了下一個分支。通常case后面要跟break 或者return語句來跳出 |
| Dead store to local variable | 該指令為局部變量賦值,但在其后的沒有對它做任何使用。 |
| Write to static field from instance method | 在實例方法寫入靜態(tài)字段 |
| Redundant nullcheck of value known to be non-null | 方法中對不為空的值進行為空的判斷 |
| Method uses the same code for two branches | 此方法使用相同的代碼,以實現(xiàn)兩個有條件的分支。檢查以確保這是不是一個編碼錯誤 |
| Exception is caught when Exception is not thrown | 在try/catch塊中捕獲異常,但是異常沒有在try語句中拋出而RuntimeException又沒有明確的被捕獲 |
| Integral division result cast to double or float | 整形數(shù)除法強制轉(zhuǎn)換為double或者float類型 |
| Possible null pointer dereference due to return value of called method | 方法的返回值沒有進行是否為空的檢查就重新賦值,這樣可能會出現(xiàn)空指針異常 |
| Useless object created | 對象創(chuàng)建了,但并沒有使用 |
| Unread public/protected field | 沒有用到的字段 |
4.3、Internationalization 代碼國際化相關(guān):
| 錯誤信息 | 說明 |
|---|---|
| Consider using Locale parameterized version of invoked method | 使用平臺默認的編碼格式對字符串進行大小寫轉(zhuǎn)換,這可能導(dǎo)致國際字符的轉(zhuǎn)換不當(dāng)。使用以下方式對字符進行轉(zhuǎn)換 |
4.4、Performance 代碼性能相關(guān):
| 錯誤信息 | 說明 |
|---|---|
| Boxing/unboxing to parse a primitive | 類型轉(zhuǎn)換,比如字符串轉(zhuǎn)換成int,應(yīng)該使用 Integer.parseInt(“”) 代替 Integer.valueOf(“”) |
| Method concatenates string using + in aloop | 每次循環(huán)里的字符串+連接,都會新產(chǎn)生一個string對象,在java中,新建一個對象的代價是很昂貴的,特別是在循環(huán)語句中,效率較低。解決辦法:使用StringBuffer或者StringBuilder重用對象 |
| Private method is never called | 私有方法沒有被調(diào)用 |
| Explicit garbage collection;extremely dubious except in benchmarking code | 在代碼中顯式的調(diào)用垃圾回收方法,這樣做并不能起作用。關(guān)閉操作或者finalize方法中調(diào)用垃圾回收方法會導(dǎo)致很多的性能浪費,這樣大規(guī)模回收對象時會造成處理器運行緩慢。 |
| Unread field:should this field be static? | 沒有用到的static 字段 |
| should be a static inner class | 此內(nèi)部類應(yīng)該使用static修飾 |
4.5、Experimental
| 錯誤信息 | 說明 |
|---|---|
| Method may fail to clean up stream or resource on checked exception | 這種方法可能無法清除(關(guān)閉,處置)一個流,數(shù)據(jù)庫對象,或其他資源需要一個明確的清理行動,解決方法:流的關(guān)閉都寫在finally里面 |
4.6、Malicious code vulnerability 惡意破壞代碼相關(guān):
| 錯誤信息 | 說明 |
|---|---|
| May expose internal representation by incorporating reference to mutable object | 此代碼把外部可變對象引用存儲到對象的內(nèi)部表示。如果實例受到不信任的代碼的訪問和沒有檢查變化,將危及對象和重要屬性的安全。解決方式:存儲一個對象的副本,在很多情況下是更好的辦法。 |
| Field isn’t final but should be | 此字段前應(yīng)該加final |
| Field isn’t final and can’t be protected from malicious code | 一個靜態(tài)字段是可以被惡意代碼或其他的包訪問修改。可以把這種類型的字段聲明為final類型的以防止這種錯誤 |
| Field should be package protected | 此字段前應(yīng)該加protected |
4.7、Multithreaded correctness 多線程代碼正確性相關(guān):
| 錯誤信息 | 說明 |
|---|---|
| Static DateFormat | DateFormat 在多線程中本身就是不安全的,如果在線程范圍中共享一個DateFormat的實例,而不使用一個同步的方法在應(yīng)用中就會出現(xiàn)一些奇怪的行為 |
| Call to static DateFormat DateFormats | 多線程使用本就是不安全的,改進方法:需要創(chuàng)建多實例或線程同步 |
4.8、Correctness 代碼正確性相關(guān):
| 錯誤信息 | 說明 |
|---|---|
| Nullcheck of value previously dereferenced | 此代碼之前沒有進行null值檢查,解決辦法:進行null檢查 |
| Possible null pointer dereference | 可能為null |
| Null pointer dereference | 對象賦為null值后,沒有被重新賦值 |
| Possible null pointer dereference in method on exception path | 在異常null值處理分支調(diào)用的方法上,可能存在對象去除引用操作 |
| value is null and guaranteed to be dereferenced on exception path exception | 分支上,存在引用一個null對象的方法,引發(fā)空指針異常 |
| Self comparison of value with itself | 方法中對一個局部變量自身進行比較運算,并可說明錯誤或邏輯錯誤。請確保您是比較正確的事情 |
| An apparent infinite recursive loop | 明顯的無限迭代循環(huán),將導(dǎo)致堆棧溢出 |
五、SonarLint:
1、整體介紹:
sonar 比 Findbugs 高了一個層級,它不僅關(guān)注常規(guī)靜態(tài)BUG,還關(guān)注到了如代碼質(zhì)量、包與包、類與類之間的依賴情況,代碼耦合情況,類、方法、文件的復(fù)雜度,代碼中是否包含大量復(fù)制粘貼的代碼,關(guān)注的是項目代碼整體的健康情況。sonar 有兩種使用方式:插件和客戶端,sonar 的插件名稱為 sonarLint。
2、安裝步驟:
通過 File > Settings > Plugins > Marketplace 搜索 “SonarLint”,按照提示進行安裝,然后重啟即可
3、使用說明:
右鍵項目或者文件進行如上圖所示操作,執(zhí)行之后可以看到如下信息,如果代碼中有不合理的地方會在report中顯示,同時點擊錯誤的地方在右邊會給出建議的修改供參考。
4、配置 SonarLint 服務(wù)端:
4.1、配置 Sonar 服務(wù)器:
sonarLint 插件的使用場景是自用自審,但 sonar 也提供了平臺版本,使用場景則是他審,sonar 平臺的搭建就不在這篇文章介紹了,感興趣的讀者可以自己上網(wǎng)查看,我們這里主要介紹如何在 sonarLint 插件中配置關(guān)聯(lián) sonar 平臺服務(wù)器的工程,進行本地檢查:
點擊新增按鈕,輸入Configuration Name,配置sonarlint 服務(wù)器的地址,然后下拉框選擇 Login/Password,輸入 sonarlint服務(wù)器的賬號密碼
4.2、具體 Sonar工程配置:
配置完服務(wù)器之后,需要針對具體工程進行配置,點擊 connection下拉框,選擇上面配置好的服務(wù)器連接,然后點擊 Search in list,找到對應(yīng)的工程:
4.3、使用 SonarLint 檢查:
配置完上面兩步之后,接下來就可以選擇要進行檢查的類或者目錄進行 sonarlint 檢查了(跟第3點的使用方式一致),同時,在 commit 代碼的時候,勾選 “Perform Sonarlint analysis”,會針對你要提交的代碼進行sonarlint檢查
總結(jié)
-
檢查代碼規(guī)范的話,直接使用
Alibaba Java Coding Guidelines就可以了 -
找 BUG 的話,使用
PMD、Findbugs、SonarLint相互補充: -
-
PMD自定義能力強,用來自定義項目BUG規(guī)則非常好用 -
Findbugs找 BUG 能力很強,我們拿找到的BUG給新員工培訓(xùn)也很好。 -
SonarLint規(guī)則豐富,比 Findbugs 能覆蓋到更全的場景
