新聞中心
本文轉(zhuǎn)載自微信公眾號「BAT的烏托邦」,作者YourBatman。轉(zhuǎn)載本文請聯(lián)系BAT的烏托邦公眾號。

前言
你好,我是方同學(xué)(YourBatman)
上篇文章【方同學(xué)】是如何高效的使用IntelliJ IDEA 再一次勾起了較多讀者對IDEA的興趣,讓我沒想到的是一個小小的IDE開發(fā)工具而已,甚至都與Java語言沒有直接關(guān)系,竟然也能寫成一個系列。也許它代表著一種態(tài)度,一種程序員對工具使用的態(tài)度,not only code。圖片認識我的朋友可能比較清楚,筆者近些年一直從事和帶領(lǐng)團隊從事基礎(chǔ)架構(gòu)、中間件的研發(fā)工作。眾所周知,寫基建代碼與業(yè)務(wù)開發(fā)有不同,它對代碼質(zhì)量、可靠性、性能、軟件長久生命力均會有更高要求,畢竟基礎(chǔ)不牢,地動山搖是共識。
本文就為你分享,筆者是如何借助IDEA自帶的一些能力,對書寫的代碼進行(質(zhì)量)審查的。工具的出生就為提效,熟練使用對個人甚至團隊都有好處。
所屬專欄
BATutopia-IntelliJ IDEA
相關(guān)下載
【女媧Knife-Initializr工程】訪問地址:https://start.yourbatman.cn 或 http://152.136.106.14:8761
Java開發(fā)軟件包(Mac):https://wangpan.yourbatman.cn/s/rEH0 提取碼:javakit
程序員專用網(wǎng)盤上線啦,開放注冊送1G超小容量,幫你實踐做減法:https://wangpan.yourbatman.cn
版本約定
IntelliJ IDEA 2021.2
正文
提高代碼質(zhì)量的手段
代碼作為軟件的載體,是軟件最為重要的組成部分。所以一個軟件的質(zhì)量如何,很大程度上是由代碼質(zhì)量決定的。也許在寫幾句hello world的時候軟件質(zhì)量尚可,但隨著時間的推移、代碼量的增加、需求的多變、團隊協(xié)作日益復(fù)雜等因素的加入,往往在質(zhì)量這條路上漸行漸遠。驀然回首,是不是感覺自己已忘初心,但依舊砥礪前行呢?
殊不知,代碼并非編譯通過,萬事大吉,編譯只是最最最最基礎(chǔ)的保證而已。
大部分程序員是期望寫出高質(zhì)量的代碼,對自己的代碼質(zhì)量要求是較高追求的。可一旦遇到趕工壓力,尤其是在 deadline 之前,就很可能會把完成度很低的代碼交出去,心想“反正有人給我檢查,到時候再說吧”。但是,這些代碼就好比是一臺“行走的Bug制造機”,后患無窮。作為你的領(lǐng)導(dǎo)看到這樣的代碼上線,可謂慌得一批。
既然趕工期、deadline這種“事件”無法避免,并且團隊內(nèi)程序員的水平/追求也高低不一,怎么辦?隨著軟件行業(yè)的發(fā)展,出現(xiàn)了一批又一批的方法論、手段、工具用于整體提升軟件質(zhì)量,下面按照離程序員由近及遠的順序從兩個方面簡要了解一下。
程序員側(cè) - 最行之有效
代碼是由程序員寫的,最了解它的莫過于程序員自己。因此在本側(cè)若能夠做好質(zhì)量把控關(guān),是最行之有效的。正所謂在離“用戶”最近的地方發(fā)現(xiàn)問題、解決問題往往效率最高的。
當(dāng)然,從品控的方式方法上,自然也有成套的解決方案。處在程序員側(cè),有個非常大的優(yōu)勢:可借助IDE提供的“超強”能力,高效的進行代碼審查工作。
IDE通用代碼審查
什么叫通用代碼審查?說白了就是關(guān)乎代碼格式、方法/變量命名、基礎(chǔ)語法合理性等等,一般的IDE都有這樣的能力。
比如本文接下來將要講的IDEA代碼審查能力,就是提供的這方面的能力。
靜態(tài)代碼檢測
借助checkstyle、p3c這類工具,對代碼進行靜態(tài)檢測,能夠提早發(fā)現(xiàn)很多運行期潛在的bug/風(fēng)險點。靜態(tài)代碼檢測對Java這種靜態(tài)語言效果極佳,這也是靜態(tài)語言的巨大優(yōu)勢之一:健壯性強。它對動態(tài)語言(如Python、PHP等)有點無能為力,效果欠佳。
拿Java舉例,像Long.equals(Integer)這種無數(shù)人踩過的坑,通過靜態(tài)代碼檢測就可以規(guī)避。另外,代碼規(guī)范、格式等等都可以通過靜態(tài)代碼檢測來實現(xiàn)很好的約束。值得注意的是,別看只是格式,這也很重要,很多時候程序出現(xiàn)bug,代碼格式才是原罪。對于一個普通的程序員來講,第一任務(wù)是要寫出人能看得懂的代碼,其次才是機器。
單元測試
單元測試(UT),是指對軟件中的最小可測試單元進行檢查和驗證。那什么叫最小可測單元呢?以Java語言為例,最小可測單元就是一個方法/函數(shù)。
寫出一個可單測的代碼其實是非常困難的,有工作經(jīng)驗的程序員或多或少經(jīng)歷過“拒絕寫單元測試”的情況,根據(jù)我的經(jīng)驗,出現(xiàn)這種畏難情緒的根本原因是:不會寫,沒有可“抄”的,畢竟ctrl c + ctrl v才是第一生產(chǎn)力嘛,讓自己去搞,沒有的事。
國內(nèi)的開發(fā)環(huán)境尚處在初、中期,普遍對單元測試的重視度不夠。主要原因我認為有兩點:
寫好UT需要花費一定時間,而國內(nèi)行情一般“工期緊”,較少做中長期規(guī)劃
業(yè)務(wù)邏輯代碼分層不夠、耦合嚴(yán)重,導(dǎo)致寫UT代碼時工作量劇增,近乎無法單測
久而久之,積重難返。等到最后上級領(lǐng)導(dǎo)說要關(guān)注代碼質(zhì)量要求寫單元測試的時候,受到的阻礙情緒將會是空前的,然后就陷入了惡性循環(huán)。
關(guān)于UT,開發(fā)者公認的事實:UT是確保代碼健壯性極其有效的手段。根據(jù)現(xiàn)實情況,我本人對UT的態(tài)度是:盡量不要自頂向下的強推,而應(yīng)疏。
單元測試其實是一門嚴(yán)重被低估的“學(xué)問”,經(jīng)常是領(lǐng)導(dǎo)大嘴一巴說要寫,至于怎么寫可能領(lǐng)導(dǎo)自己也不知道,甚至可能從來沒寫過。正所謂己所不欲勿施于人,我認為UT覆蓋率問題應(yīng)該上升到方案級別,而不只是只有一個字:寫。
畏難情緒是順人性的,是天性的表現(xiàn)。在代碼的世界了,不會才覺得難,才會抗拒。畢竟寫UT遠沒有寫業(yè)務(wù)代碼來得那么的“輕松”。針對此問題,可采用榜樣的力量逐步疏通、滲透。對于個人來講,應(yīng)該迎難而上,追求更高質(zhì)量的代碼。
CI/CD側(cè) - 統(tǒng)一卡點
雖然說在程序員側(cè)進行一些質(zhì)量把控環(huán)節(jié)效果是最佳的,但此方式高度依賴程序員本身的綜合水平和自覺性,可靠性是明顯不夠的。因此在實際生產(chǎn)上,需要輔助一些集中式卡點行為來做保障。
Code Review
對每個提測的分支,(至少在上線前)必須要進行CR(code review)環(huán)節(jié)。此環(huán)節(jié)比較出名的工具有:Gitlab(商業(yè)版)、Fisheye等
集中式靜態(tài)代碼檢測
簡而言之,就是將你本地靜態(tài)代碼監(jiān)測的能力搬到云端,進行集中檢測。一般可分為全量檢測和增量檢測。此環(huán)節(jié)比較出名的工具有:sonar、cubase等
集成測試
對多個系統(tǒng)進行集成測試、邊界測試。該環(huán)節(jié)一般屬于QA人工介入階段,和業(yè)務(wù)邏輯強關(guān)聯(lián),是最為耗時的階段之一。
持續(xù)集成流水線工具
在軟件發(fā)布階段,也會有一些相應(yīng)的審核、卡點機制。此環(huán)節(jié)比較出名的工具有:jenkins、hudson等
借助IDEA審查你的代碼
做個小調(diào)查:有多少同學(xué)從來沒有使用過甚至從來沒有看過IDEA的code菜單呢?
不管你看沒看過,應(yīng)該直接或間接的使用過其相關(guān)功能。比如這個Generate...
自動為JavaBean生成get/set方法、構(gòu)造器、hashCode()、toString()等方法。也許你會說現(xiàn)在用lombok基本不使用它了,對,這是事實。但是,再不濟,像Override Methods、Implement Methods這些功能都用過吧,畢竟我不信方法復(fù)寫、方法實現(xiàn)這種模板代碼你會一字一句手敲~
那么,接下來重點向你介紹code菜單里面的代碼審查功能,順帶也分享筆者是如何利用IDEA提供的這些能力去幫助自己、甚至幫助團隊提高代碼質(zhì)量、保證代碼質(zhì)量的。
代碼審查相關(guān)功能在Code菜單這里(如下圖)。兩條灰色的線條將這幾項歸為一類:
以這段示例代碼為例審查:
- package cn.yourbatman;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.autoconfigure.AutoConfigureAfter;
- @SpringBootApplication
- public class Application {
- private String name;
- private String agee;
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- public boolean fun1(boolean bool) {
- return bool ? true : false;
- }
- public String fun2(String s) {
- return s.toString();
- }
- }
Inspect Code...審查你的代碼
Inspect:檢查、審查。
點擊OK運行,在problem視窗里可以看到“有問題”的代碼:
經(jīng)過審查,本工程里的“壞味道”代碼就在problem視窗指出了。如圖,IDEA針對性的提供了便捷的一鍵處理按鈕,你可以快速處理,非常智能化和人性化有木有。
到這,你可能不禁想問:IDEA怎么知道這是壞味道代碼的?遵照什么規(guī)則?顯然,一切都是“有法可依”,它在這:設(shè)置 -> Editor -> Inspections
一般來講,Inspections保持默認即可。但我會把拼寫檢查(畢竟英語并非咱母語,偶爾單詞拼寫錯誤甚至用拼音是可以原諒的,關(guān)掉它以節(jié)約點性能開銷嘛)相關(guān)的關(guān)掉:Spelling、Typo
注意:Inspect Code只會幫你把壞味道代碼“揪出來”,改還是不改的決策權(quán)還在于你自己。
Code Cleanup...精煉你的代碼
不同于Inspect Code幫你指出壞味道的代碼,它比較“狠”,會拿你的代碼直接開刀。如下:
執(zhí)行該動作不需要同意,IDEA會直接動手修改你的代碼。
當(dāng)然嘍,你duck不必擔(dān)心它改亂了:它有且只做同等語義的替換,使得代碼組織起來更優(yōu)雅,絕不會影響到程序的正確執(zhí)行。
Tips:有時候人容易理解和優(yōu)雅寫法是相沖的,這個時候你就得三思是否有必要執(zhí)行此功能嘍
Analyze Code...分析你的代碼
它是一個功能集的統(tǒng)稱。
問:為何這些功能被放在二級目錄下?答:相對來說不太常用。這是基本的產(chǎn)品設(shè)計邏輯嘛:常用的放在一級目錄,不常用的功能下層
Silent Code Cleanup
靜悄悄的完成精煉你的代碼操作,執(zhí)行結(jié)果同Code Cleanup。我的使用情況:基本不用
Run Inspection by name
如果覺得每次運行Inspect Code把所有的規(guī)則都走一遍太慢了,那么就可以使用此功能:只運行指定名稱的規(guī)則
我的使用情況:基本不用。現(xiàn)在微服務(wù)開發(fā)模式,每個應(yīng)用“體積”都很小,1s和0.5s的差異who care呢
View Offline Inspection Results
離線查看代碼分析的結(jié)果。此功能的存在,是因為problem結(jié)果是可以導(dǎo)出的:
我的使用情況:只使用過幾次。那是我要給團隊做分享,所以通過導(dǎo)出文件來保留“現(xiàn)場”,從而在分享時在導(dǎo)入方便說明問題。
Infer Nullify
Infer:推斷。此功能作用是在方法參數(shù)、返回值里幫你推斷:哪些必須不能為null、哪些可以為null
以這個方法為例:
- public String fun2(String s) {
- return s.toString();
- }
內(nèi)部調(diào)用了s的toString()方法,因此s肯定不能為null,進而推斷出返回值也就不可能為null。因此,運行IDEA的此功能后,代碼會被改成這樣:方法簽名的語義更加明確
- public @NotNull String fun2(@NotNull String s) {
- return s.toString();
- }
值得注意的是,注解它只用于表達語義,運行期無任何作用。另外,該功能要正常執(zhí)行需要此依賴包才行:
若沒有此依賴,執(zhí)行時會彈出提示你添加依賴:
此時點擊ok就能自動幫你把依賴加上了,非常方便。
Tips:點ok后此框不會消失,但實際依賴已經(jīng)加上,不用重復(fù)點哦,否則會重復(fù)添加依賴的。這是IDEA的一個小bug
我的使用情況:從未使用過。因為我習(xí)慣使用功能更強大的Bean Validation,不僅語義明確,runtime時期也會生效。
Locate Duplicate
顧名思義,幫你定位重復(fù)代碼,以便做封裝、抽象。
我的使用情況:在review組員代碼的時候,用得較多。查找結(jié)果還是蠻有參考價值的,推薦使用
Dependencies...
IDEA在Project視窗,把依賴統(tǒng)一全部放在了External Libraries里,就像這樣:
若是一個多模塊的項目,此時只想查看某1個模塊的依賴的話,通過External Libraries就無能為力了。這個時候一般有兩種辦法來查看具體某個模塊的依賴:
通過Maven視窗查看
這種方式,它對于中小型服務(wù)可以解決絕大部分問題,因為依賴不多不難定位。但是它的明顯缺點是:不夠直觀。并不能一眼看出來模塊的最終依賴。比如某個依賴是間接依賴進來的,這時通過這種方式就非常不直觀了;又比如多個地方引入了a.jar,也就無法一眼看出來最終使用的是哪個版本的a.jar啦
通過本處的Dependencies功能
這個依賴分析功能非常、非常、非常強大。它不僅僅能幫你分析出每個類(粒度非常細)依賴哪些庫,還能分析出依賴了本project的哪些類。該功能在閱讀他人代碼(or開源代碼)時非常有用
我的使用情況:較為頻繁。我在閱讀開源代碼的時候使用較多,通過依賴分析,能夠較快的掌握作者的整體設(shè)計意圖,具有更全面的視野。
Backward Dependencies...
上面功能是查看自己依賴了誰,該功能表示誰依賴了自己。
Module、Cycle Dependencies...
用于分析本工程的模塊粒度的依賴關(guān)系,是否存在循環(huán)依賴等,使用起來比較簡單,不詳細解釋了。
Analyze Stack Trace or Thread Dump...
又一神器,這個工具我可太愛了。字面含義:分析堆棧,或者內(nèi)存dump。
例如有這么一個場景:線上服務(wù)出bug拋了異常,日志文件里留下的是堆棧信息,面對這個堆棧信息你如何快速定位到問題代碼呢?
這個時候一般是在這個黑框里逐行的找,找到“熟悉”的一行(有行號),然后返回到IDEA里找到對應(yīng)的類,問題定位路徑其實還蠻長的。
其實duck不必這么麻煩,IDEA為咱們提供了非常好用的分析工具,你只需要:
- 復(fù)制堆棧信息
- 在IDEA里Code -> Analyze Stack Trace or Thread Dump打開分析窗口
點擊ok,控制臺里就能顯示出堆棧信息,和本地調(diào)試一模一樣的效果了有木有。
這里我演示的是該功能的最簡單使用場景,除了分析這種簡單的堆棧外,還可以分析dump文件,還可以自定義分析器(比如class文件混淆、加密了)等等,最終目的就是讓開發(fā)者有種本地化“分析線上問題”的體驗。
關(guān)于本功能的更多使用方式,感興趣的同學(xué)在真正用起來的時,可自己發(fā)現(xiàn)。
總結(jié)
本文以IDEA作為著力點,我主要想輸出的兩個觀點是:
- 單元測試被低估了
- IDEA的代碼審查能力被低估了
作為一個開發(fā)者,很多時候人與人的差異體現(xiàn)在知道的多與少、知道和不知道上,畢竟大家的教育背景、智商大都差異不大,會得多一點并且讓這些能支撐自己總是好的。
分享文章:利用IDEA代碼審查能力,來保證代碼質(zhì)量
轉(zhuǎn)載源于:http://m.fisionsoft.com.cn/article/cdpiedi.html


咨詢
建站咨詢
