CheckStyle是什么?
CheckStyle是SourceForge下的一個項目,提供了一個幫助JAVA開發人員遵守某些編碼規范的工具。它能夠自動化代碼規范檢查過程,從而使得開發人員從這項重要,但是枯燥的任務中解脫出來[1]。
2.2. CheckStyle檢驗的主要內容
CheckStyle默認提供一下主要檢查內容:
·Javadoc注釋
·命名約定
·標題
·Import語句
·體積大小
·空白
·修飾符
·塊
·代碼問題
·類設計
·混合檢查(包活一些有用的比如非必須的System.out和printstackTrace)
從上面可以看出,CheckStyle提供了大部分功能都是對于代碼規范的檢查,而沒有提供象PMD和Jalopy那么多的增強代碼質量和修改代碼的功能。但是,對于團隊開發,尤其是強調代碼規范的公司來說,它的功能已經足夠強大。
2.3. CheckStyle的主要運行方式
目前,CheckStyle的版本是3.0,與以前的版本不同,它的配置文件是基于XML而非Properties文件。
它的3.0版本提供了兩種運行的方式:
·命令行工具
·ANT任務
同時,CheckStyle目前有很多針對流行IDE的插件,例如Eclipse、IntelliJ IDEA、JBuilder等。但是,大部分都是基于2.4的版本,新版本的特性不支持,同時配置也較為復雜。
因為一般情況下,如果與開發過程與環境集成起來,編碼規范的檢查會更加有效,因此,作為ANT任務的運行方式使用的更加普遍。
在ANT的build.xml文件中添加CheckStyle任務的步驟如下:
1. 將checkstyle-all-3.1.jar拷貝到項目的LIB目錄;
2. 建立配置文件;
3. 聲明CheckStyle任務:
<taskdef resource="checkstyletask.properties" classpath="${lib}/checkstyle-all-3.1.jar"/>
4. 建立CheckStyle任務:
<target name="checkstyle">
<checkstyle c>
<fileset dir="${src}" includes=" **/*.java" />
</checkstyle>
</target>
2.4. 定制CheckStyle
CheckStyle的執行基于XML配置文件,它的主要組成部分是:
·Module:整個配置文件就是一棵Module樹。根節點是Checker Module。
·Properties:它來決定一個Module如何進行檢查。每個Module都有一個默認值,如果不滿足開發需求,可以設定其它的值。
下面是一個示例:
<module name="MethodLength">
<property name="max" value="60"/>
</module>
它表示,如果方法或者構造函數的長度超過60行,CheckStyle就會報錯。而默認值是150行。
以下是一段CheckStyle對于Maven項目源文件的檢查報告:
Method 'createExpression' is not designed for extension - needs to be abstract, final or empty. 91
Unable to get class information for JellyException. 91
Line has trailing spaces. 93
Line has trailing spaces. 104
Method 'evaluate' is not designed for extension - needs to be abstract, final or empty. 113
Parameter context should be final. 113
Line has trailing spaces. 130
Method 'getExpressionText' is not designed for extension - needs to be abstract, final or empty. 131
Line has trailing spaces. 134
Line has trailing spaces. 135
Method 'toString' is not designed for extension - needs to be abstract, final or empty. 137
Method 'isSupportAntVariables' is not designed for extension - needs to be abstract, final or empty. 156
Method 'setSupportAntVariables' is not designed for extension - needs to be abstract, final or empty. 168
Parameter supportAntVariables should be final. 168
'supportAntVariables' hides a field. 168
Method 'isValidAntVariableName' is not designed for extension - needs to be abstract, final or empty. 183
Parameter text should be final. 183
一般情況下,與IDE集成在一起使用的時候,點擊出錯的條目,可以跳轉到相應的代碼。
本貼來自ZDNetChina中文社區http://bbs.zdnet.com.cn,本貼地址:http://bbs.zdnet.com.cn/viewthread.php?tid=178617
三、CheckStyle的最佳實踐
3.1. Sun’s Code Conventions的修改
在CheckStyle的最新發布版本中,有一個對于Sun的Java編碼規范的配置文件信息。但是,其中有很多條目并不一定符合項目開發的需要。就算是對于很多優秀的開源項目,按照這個規范來進行檢查,也會出現成千上萬的錯誤。
下面提出的一些修改意見,是從實際項目執行過程中總結出來的,可以作為大家的參考。我們以CheckStyle3.0配置文件的順序來介紹:
1. 去除對于每個包都有一個package.html文件的限制;
<!--<module name="PackageHtml"/>-->
2. 修改對于JavaDoc Comments的限定:對于很多使用Code Generator的項目來說,需要將手寫代碼與生成代碼、單元測試代碼的檢查分開進行;
3. 修改對于體積大小的限制:目前,很多顯示器都是17寸,而且打印方面的限制也比以前有所改善,同時,由于代碼中Factory等模式的運用,以及有意義的 方法名稱等約定,默認每行代碼的長度(80)是遠遠不能滿足要求;對于方法長度等等,也應該根據項目情況自行決定:
<module name="FileLength"/>
<module name="LineLength">
<property name="max" value="120"/>
</module>
<module name="MethodLength">
<property name="max" value="300"/>
</module>
<module name="ParameterNumber"/>
4. 修改對于Throws的的限制:允許Throws Unchecked Exception以及Throws Subclass Of Another Declared Exception。
<module name="RedundantThrows">
<property name="allowUnchecked" value="true"/>
<property name="allowSubclasses" value="true"/>
</module>
5. 修改成員變量的可視性:一般情況下,應該允許Protected Members以及Package Visible Members。
<module name="VisibilityModifier">
<property name="protectedAllowed" value="true"/>
<property name="packageAllowed" value="true"/>
</module>
3.2. CheckStyle應用的最佳實踐
采用CheckStyle以后,編碼規范的檢查就變得及其簡單,可以作為一項切實可行的實踐加以執行。
一般情況下,在項目小組中引入CheckStyle可以按照下面的步驟進行:
1. 強調Code Review與Code Conventions的重要作用;
2. 介紹CheckStyle;
3. 初步應用CheckStyle:參照CheckStyle附帶的配置文件,酌情加以剪裁,在項目的Ant配置文件中,添加CheckStyle任務,可以單獨執行;
4. 修改、定型CheckStyle的配置文件:按照基本配置文件執行一段時間(2~3周),聽取開發人員的反饋意見,修改配置信息;
5. 作為開發過程的日常實踐,強制執行CheckStyle:穩定CheckStyle的配置信息,同時將CheckStyle任務作為Build的依賴任務 或者配置源碼控制系統(目前,CheckStyle可以與CVS有效集成),使得代碼在加入系統之前必須通過檢查。
同時需要指出的是,CheckStyle的有效執行需要依賴兩個條件:
·Ant的廣泛應用:CheckStyle基于Ant執行的方式比較容易,而且可以在項目內容形成一致的執行環境。同時,也比較容易與其它任務,例如Build等發生關聯。
·IDE Format Code的強大功能:由于CheckStyle本身并沒有提供很強大的Code Format等功能,因此,需要借助IDE的幫助,從而使得在發生錯誤的時候,可以很容易的進行修復。目前,主流的Java IDE都提供了這方面的功能,IDEA在這方面尤其突出。它提供的統一、可定義的Code Format Template(項目小組內部可以使用統一模板)以及方便的快捷鍵功能(Ctrl+Alt+T:Format Code, Ctrl+Alt+O:Optimize Import等)。
四、結論
利用CheckStyle可以方便的對于編碼的Code Conventions進行檢查,同時,也有效地減少了Code Review的工作,使得Reviw人員的精力更多的集中到邏輯和性能檢查。
Checkstyle的結果輸出
序號 輸出內容意義
1 Type is missing a javadoc commentClass 缺少類型說明
2“{” should be on the previous line “{” 應該位于前一行
3Methos is missing a javadoc comment方法前面缺少javadoc注釋
4Expected @throws tag for “Exception”在注釋中希望有@throws的說明
5“.” Is preceeded with whitespace “.” 前面不能有空格
6“.” Is followed by whitespace“.” 后面不能有空格
7“=” is not preceeded with whitespace“=” 前面缺少空格
8“=” is not followed with whitespace“=” 后面缺少空格
9“}” should be on the same line“}” 應該與下條語句位于同一行
10Unused @param tag for “unused”沒有參數“unused”,不需注釋
11Variable “CA” missing javadoc變量“CA”缺少javadoc注釋
12Line longer than 80characters行長度超過80
13Line contains a tab character行含有”tab” 字符
14Redundant “Public” modifier冗余的“public” modifier
15Final modifier out of order with the JSL suggestionFinal modifier的順序錯誤
16Avoid using the “.*” form of importImport格式避免使用“.*”
17Redundant import from the same package從同一個包中Import內容
18Unused import-java.util.listImport進來的java.util.list沒有被使用
19Duplicate import to line 13重復Import同一個內容
20Import from illegal package從非法包中 Import內容
21“while” construct must use “{}”“while” 語句缺少“{}”
22Variable “sTest1” must be private and have accessor method變量“sTest1”應該是private的,并且有調用它的方法
23Variable “ABC” must match pattern “^[a-z][a-zA-Z0-9]*$”變量“ABC”不符合命名規則“^[a-z][a-zA-Z0-9]*$”
24“(” is followed by whitespace“(” 后面不能有空格 25“)” is proceeded by whitespace“)” 前面不能有空格
不太明白的錯誤解答
1. 'X' hides a field.
public class Foo
{
private int bar;
public Foo(int bar)
{
this.bar = bar;
}
public final int getBar()
{
return bar;
}
}
解釋:全局private int bar;和局部public Foo(int bar)的bar變量名字重復。
此錯誤,可以忽略不檢查。
2. Parameter X should be final.
public class Foo
{
private int bar;
public Foo(int bar)
{
this.bar = bar;
}
public final int getBar()
{
return bar;
}
}
解釋:public Foo(int bar)的局部變量,被認為是不可改變的,檢查需要加上final關鍵字定義public Foo(final int bar)
此錯誤,可以忽略不檢查。
3. Redundant 'X' modifier.
public interface CacheHRTreeService extends Manager {
/**
* Organization Tree
*
* @param orgDto
* @return
* @throws Exception
*/
public void setOrganization(OrganizationDTO orgDto) throws Exception;
/**
* Organization Tree
*
* @return
* @throws Exception
*/
public OrganizationDTO getOrganization() throws Exception;
......
}
解釋:多余的字段。public OrganizationDTO getOrganization() throws Exception;此時public為多余的字段,因為interface定義的時候,就是public的。
需要檢查。
4. - Class X should be declared as final.
解釋:對于單例設計模式,要求返回唯一的類對象。但是HRFactory和ContextFactory為優化的兩個類,不需求檢查。
其他的單例類,依然需要進行檢查。
5. Utility classes should not have a public or default constructor.
解釋:工具類不必提供默認的構造方法。
需要檢查,僅僅為提示。
6. File does not end with a newline.
解釋:雖然JAVA程序不要求結尾要用新行,但是習慣上應該要空一行。
需要檢查,僅僅為提示。
7. - Method 'addChildrenId' is not designed for extension - needs to be
abstract, final or empty.
解釋:通過父類繼承的,此類有點特殊
可以忽略此類。
8. Variable 'id' must be private and have accessor methods.
解釋:BaseHRDTO類,為父類,屬性給子類繼承,比較特殊。
但是其他的類,聲名需要加上范圍'private'關鍵字
需要檢查。
9. -Array brackets at illegal position.
解釋:代碼寫法,習慣不一樣。
需要檢查,僅僅提示。