融入團隊代碼風格,代碼越寫越爛!

架構的小事 2024-05-10 01:53:44

來源:https://mp.weixin.qq.com/s/69OtY2LmDrySKICAoqV7mQ

作者:Java3y

最近是真的有點忙啊,需求和bug都排到下一個月了,難得今天休息有空上來扯扯,主題是有關代碼質量問題的。

在我初學的時候,我是挺喜歡專研各種Java語法和性能相關的問題的。舉個很明顯的例子,我們都知道Java的單例模式有好幾種寫法,什麽餓漢式、簡單懶漢式(在方法聲明時加鎖)、DCL雙重檢驗加鎖(進階懶漢式)、靜態內部類(優雅懶漢式)、枚舉。

這貌似算是Java的高頻面試題了,所以這幾種寫法的優缺點幾乎都已經被說爛了。

1、所謂「餓漢式」指的就是還沒被用到,就直接初始化了對象。(浪費內存) 2、所謂「懶漢式」指的就是等用到的時候,才進行初始化。(不浪費內存)

在剛學明白的時候,我一想:“我這以後肯定是用懶漢式啊,對內存多友好。我不用簡單懶漢式(在方法聲明時加鎖),這會影響到性能。我可以用雙重檢驗加鎖(進階懶漢式)或者靜態內部類(優雅懶漢式)”。

後來工作了以後,發現工作代碼裏什麽牛鬼邪神都有,逐漸發現:代碼也不是不能跑,編譯器遠比我們想象得更加強。

于是,我用個錘子的懶漢式,我反手就是new出一個單例,代碼多簡單優雅。我堂堂一個Java開發工程師,我還缺那點小內存?真可笑。

剛進團隊的時候還想重構髒代碼,後來隨著需求的累積,又有編譯器給兜底,也沒人code review監管,寫代碼就越來越隨意了,融入團隊代碼風格就完事了。

後來出了點小故障,影響到線上的正常業務了,最後發現是髒代碼導致的,被老板吐槽了。讓我去找找有哪些工具可以排查下有沒有類似的問題(代碼質量檢查),我一想,項目這裏面的代碼的坑也太多了,不好搞啊。

工作還是得繼續幹的,既然是代碼質量檢查,找些IDEA現成的插件就OK咯。

Alibaba Java Coding Guidelines

集成了阿裏巴巴的代碼規範和最佳實踐,幫助開發者保持代碼質量和一致性,austin項目也一直用這個插件做代碼的掃描。

CheckStyle

以下是 CheckStyle 插件的一些常見功能和用途:

代碼規範檢查:CheckStyle 插件會分析項目中的源代碼,並根據預定義的規則檢查代碼,包括縮進、命名約定、代碼注釋、代碼結構等。它可以幫助團隊確保代碼風格一致,符合公司或項目的規範。自定義規則:您可以自定義 CheckStyle 規則,以便根據您的項目需求和編碼標准添加自定義規則。這使得 CheckStyle 插件非常靈活,可以適應各種項目。代碼質量改進:通過檢查代碼中的潛在問題和不良實踐,CheckStyle 插件可以幫助開發者識別和修複代碼中的問題,從而提高代碼質量。

比如,我設置了一個規則文件:

<?xml version="1.0"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"><!--checkStyle --><module name="Checker"> <!-- 檢查文件是否以一個空行結束 --> <module name="NewlineAtEndOfFile"/> <!-- 文件長度不超過1500行 --> <module name="FileLength"> <property name="max" value="1500"/> </module> <!-- 長度檢查 --> <!-- 每行不超過140個字符 --> <module name="LineLength"> <property name="fileExtensions" value="java"/> <property name="max" value="140"/> <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/> </module> <!--禁止打印e.printStackTrace錯誤信息--> <module name="RegexpSingleline"> <property name="format" value="printStackTrace"/> <property name="message" value="Prohibit invoking printStackTrace in source code !"/> </module> <!-- 每個java文件一個語法樹 --> <module name="TreeWalker"> <!-- import檢查--> <!-- 避免使用* --> <module name="AvoidStarImport"> <property name="excludes" value="java.io,java.net,java.lang.Math"/> <!-- 實例;import java.util.*;.--> <property name="allowClassImports" value="false"/> <!-- 實例 ;import static org.junit.Assert.*;--> <property name="allowStaticMemberImports" value="true"/> </module> <!-- 檢查是否導入了多余的包 --> <module name="RedundantImport"/> <!-- 沒用的import檢查,比如:1.沒有被用到2.重複的3.import java.lang的4.import 與該類在同一個package的 --> <module name="UnusedImports"/> <!-- 注釋檢查 --> <!-- 檢查構造函數的javadoc --> <module name="JavadocType"> <!--允許位置的tag如@date,@description等--> <property name="allowUnknownTags" value="true"/> <message key="javadoc.missing" value="類注釋:缺少Javadoc注釋。"/> </module> <!--方法注釋--> <module name="JavadocMethod"> <property name="tokens" value="METHOD_DEF"/> <!--允許get set 方法沒有注釋--> <!-- <property name="allowMissingPropertyJavadoc" value="true"/>--> <message key="javadoc.missing" value="方法注釋:缺少Javadoc注釋。"/> </module> <!--校驗方法的注釋--> <module name="MissingJavadocMethod"> <!--允許get set 方法沒有注釋--> <property name="allowMissingPropertyJavadoc" value="true"/> <!--允許構造方法沒有注釋--> <!-- <property name="" value="true"/>--> <property name="scope" value="private"/> </module> <!-- 命名檢查 --> <!-- 局部的final變量,包括catch中的參數的檢查 --> <module name="LocalFinalVariableName"/> <!-- 局部的非final型的變量,包括catch中的參數的檢查 --> <module name="LocalVariableName"/> <!-- 包名的檢查(只允許小寫字母),默認^[a-z]+(\.[a-zA-Z_][a-zA-Z_0-9_]*)*$ --> <module name="PackageName"> <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/> <message key="name.invalidPattern" value="包名 ''{0}'' 要符合 ''{1}''格式."/> </module> <!-- 僅僅是static型的變量(不包括static final型)的檢查 --> <module name="StaticVariableName"/> <!-- Class或Interface名檢查,默認^[A-Z][a-zA-Z0-9]*$--> <module name="TypeName"> <property name="severity" value="warning"/> <message key="name.invalidPattern" value="名稱 ''{0}'' 要符合 ''{1}''格式."/> </module> <!-- 非static型變量的檢查 --> <module name="MemberName"/> <!-- 方法名的檢查 --> <module name="MethodName"/> <!-- 方法的參數名 --> <module name="ParameterName "/> <!-- 常量名的檢查(只允許大寫),默認^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$ --> <module name="ConstantName"/> <!-- 定義檢查 --> <!-- 檢查數組類型定義的樣式 --> <module name="ArrayTypeStyle"/> <!-- 檢查long型定義是否有大寫的“L” --> <module name="UpperEll"/> <!-- 方法不超過100行 --> <module name="MethodLength"> <property name="tokens" value="METHOD_DEF"/> <property name="max" value="100"/> </module> <!-- 方法的參數個數不超過5個。 並且不對構造方法進行檢查--> <module name="ParameterNumber"> <property name="max" value="5"/> <property name="ignoreOverriddenMethods" value="true"/> <property name="tokens" value="METHOD_DEF"/> </module> <!-- 空格檢查--> <!-- 方法名後跟左圓括號"(" --> <module name="MethodParamPad"/> <!-- 在類型轉換時,不允許左圓括號右邊有空格,也不允許與右圓括號左邊有空格 --> <module name="TypecastParenPad"/> <!-- 檢查在某個特定關鍵字之後應保留空格 --> <module name="NoWhitespaceAfter"/> <!-- 檢查在某個特定關鍵字之前應保留空格 --> <module name="NoWhitespaceBefore"/> <!-- 操作符換行策略檢查 --> <module name="OperatorWrap"/> <!-- 圓括號空白 --> <module name="ParenPad"/> <!-- 檢查分隔符是否在空白之後 --> <module name="WhitespaceAfter"/> <!-- 檢查分隔符周圍是否有空白 --> <module name="WhitespaceAround"/> <!-- 修飾符檢查 --> <!-- 檢查修飾符的順序是否遵照java語言規範,默認public、protected、private、abstract、static、final、transient、volatile、synchronized、native、strictfp --> <module name="ModifierOrder"/> <!-- 檢查接口和annotation中是否有多余修飾符,如接口方法不必使用public --> <module name="RedundantModifier"/> <!-- 代碼塊檢查 --> <!-- 檢查是否有嵌套代碼塊 --> <module name="AvoidNestedBlocks"/> <!-- 檢查是否有空代碼塊 --> <module name="EmptyBlock"/> <!-- 檢查左大括號位置 --> <module name="LeftCurly"/> <!-- 檢查代碼塊是否缺失{} --> <module name="NeedBraces"/> <!-- 檢查右大括號位置 --> <module name="RightCurly"/> <!-- 代碼檢查 --> <!-- 檢查空的代碼段 --> <module name="EmptyStatement"/> <!-- 檢查在重寫了equals方法後是否重寫了hashCode方法 --> <module name="EqualsHashCode"/> <!-- 檢查子表達式中是否有賦值操作 --> <module name="InnerAssignment"/> <!-- 檢查是否有"魔術"數字 --> <module name="MagicNumber"> <property name="ignoreNumbers" value="0, 1"/> <property name="ignoreAnnotation" value="true"/> </module> <!-- 檢查switch語句是否有default --> <module name="MissingSwitchDefault"/> <!-- 檢查是否有過度複雜的布爾表達式 --> <module name="SimplifyBooleanExpression"/> <!-- 檢查是否有過于複雜的布爾返回代碼段 --> <module name="SimplifyBooleanReturn"/> <!-- 類設計檢查 --> <!-- 檢查類是否爲擴展設計l --> <!-- 檢查只有private構造函數的類是否聲明爲final --> <module name="FinalClass"/> <!-- 語法 --> <!-- String的比較不能用!= 和 == --> <module name="StringLiteralEquality"/> <!-- 限制for循環最多嵌套2層 --> <module name="NestedForDepth"> <property name="max" value="2"/> </module> <!-- if最多嵌套3層 --> <module name="NestedIfDepth"> <property name="max" value="3"/> </module> <!-- 檢查未被注釋的main方法,排除以Application結尾命名的類 --> <module name="UncommentedMain"> <property name="excludedClasses" value=".*[Application,Test]$"/> </module> <!-- 禁止使用System.out.println --> <module name="Regexp"> <property name="format" value="System\.out\.println"/> <property name="illegalPattern" value="true"/> </module> <!-- return個數 3個--> <module name="ReturnCount"> <property name="max" value="3"/> </module> <!--try catch 異常處理數量 3--> <module name="NestedTryDepth "> <property name="max" value="3"/> </module> </module></module>

當我寫出幾層for循環的時候和常量的時候,就會被掃描和監控到。

FindBugs

以下是Bug IDEA插件的一些常見用途和功能:

靜態代碼分析:Bug IDEA插件可以執行靜態代碼分析,以檢測潛在的編碼錯誤、代碼風格問題和性能問題。它可以識別諸如未使用的變量、空指針異常、不一致的縮進、未處理的異常等問題。代碼質量評估:該插件可以生成代碼質量報告,幫助開發人員了解代碼的質量水平。這些報告通常包括代碼複雜性、代碼覆蓋率、代碼重複率等指標。檢查代碼規範:Bug IDEA插件可以根據您選擇的編碼標准或規範檢查代碼,確保團隊的代碼風格一致性,並提供建議以改進代碼。自動修複問題:插件通常提供了自動修複選項,可以幫助開發人員快速修複代碼中的問題,提高代碼的質量和可維護性。安全漏洞檢測:有些Bug IDEA插件還可以檢測潛在的安全漏洞,如SQL注入、跨站腳本攻擊等,以提高應用程序的安全性。代碼重構建議:插件還可以提供有關代碼重構的建議,幫助改進代碼的結構和性能。

在這個位置可以掃描

掃描的結果:

SonarLint

SonarLint提供了更廣泛的代碼質量和安全性檢查,讓你在編寫代碼的過程中就能發現和解決問題。相比之下,FindBugs更專注于靜態代碼分析,幫助開發人員發現潛在的bug模式。

下載IDEA插件:

在這個位置可以使用掃描:

能掃描出很多的優化建議:

就這些吧,等我把austin的代碼都改改,通過了各種插件的掃描,再來推薦下我的股東服務

0 阅读:46

架構的小事

簡介:感謝大家的關注