文章分類

2011年9月16日 星期五

[應用]用來檢核你寫的JAVA程式的好用工具 - CheckStyle,Find Bugs與PMD

<Findbugs簡介>

   程式找出的問題還會依嚴重程式分成 HIGH, NORMAL, LOW 等等級,不過建議還是全都都需要正視並處理(所以選擇low,可讓FindBugs好好檢查你的程式並釋出所有的warnning)
  bug patterns
Bad practice 不好的習慣
  HE:類定義了equals(),卻沒有hashCode()
  SQLPrepared Statement是由一個非常數(變動的)的字串產生
Correctness 程式碼的正確性
  NPnull pointer被使用,沒有檢查參數或方法是否為null
Internationalization 國際化
  當對字串使用upperlowercase方法,如果是非英文的字串,可能會不恰當的轉換 
Malicious code vulnerability 程式碼弱點(可能受到的惡意攻擊)
  FI:一個classfinalize()方法(回收物件)應該是protected,而不是public
Multithreaded correctness 多執行緒的正確性
  SCconstructor使用了Thread.start(),當該類被繼承可能會導致錯誤使用空的synchronized() {}區塊,可能無法完全達到預期的結果
Performance 效能(可能導致性能不佳的程式碼)
  SS:如果屬性被宣告為final,它應該也同時考慮宣告static
  DM:用類似Integer.toString(1)代替new Integer(1).toString();應該用靜態的valueOf方法(Boolean.valueOf(…), String.valueOf(…)…)
  Dodgy 小問題(可能runtime產生錯誤)
  INT:沒必要的整數比較,如X <= Integer.MAX_VALUE
  NP:對方法直接引用,而方法可能返回null
  ICAST:整數相乘結果轉化為long數字,應該將整先轉化為long數字再相乘
  DLS:對一個local變數值,但卻沒有使用該變數
Security 安全性
  Dm: Hardcoded constant database password
  SQLPrepared Statement是由一個非常數(變動的)的字串產生
  HRS: 避免直接將http參數寫入http header裡,應用URL-encode後再加入
Experimental 實驗性
  OBL: 當方法開啟了stream或其他資源(database),使用try/finally確認方法在回傳之前釋放掉資源
更多請參考:
 
<PMD簡介>
有點類似FindBugs,但是主要是偏重Best Practice(好習慣!)的要求,最好也能盡量遵守,從他的建議可以學到不少東西。
PMD可做些甚麼,例如:
  可能會有bug的地方(possible bugs) - 空的try/catch/finally/switch描述句
  未使用到的程式碼(dead code) 區域變數、private method
  較不優的程式碼(suboptimal code) - 效率不良的使用 String/ StringBuffer
  太複雜的寫法(overcomplicated expressions) 過多的if使用、while可以取代for即可做到的事
  重複的程式碼 (duplicated code) – copy/paste的程式碼有可能bug也被複製了
  資源釋放:ConnectResultStatement使用後要確認釋放
 
<CheckStyle簡介>

檢查項目
EqualsAvoidNull
說明
使用equals() method時,避免潛在的NullPointerException疑慮

屬性
範例:
-不好的
String nullString = null;
nullString.equals("My_Sweet_String");

-好的
String nullString = null;
"My_Sweet_String".equals(nullString);



檢查項目
JavadocMethod
說明
檢查方法是否有javadoc註解

屬性
說明
預設值
scope
檢查範圍
public
logLoadErrors
是否載入javadoc註解中所提及的@throws exception classes
true
範例:

檢查項目
NeedBraces
說明
檢查必須使用括號{}

屬性
說明
預設值
範例:
不好的:
if(true)
    a = 0;



好的:
if(true){
    a = 0;
}






檢查項目
AvoidNestedBlocks
說明
檢查是否有使用多餘的括號

屬性
說明
預設值
範例:
public void guessTheOutput()
{
    int whichIsWich = 0;
    {   //多餘的
        int whichIsWhich = 2;
    }
    System.out.println("value = " + whichIsWhich);
}


檢查項目
JavaNCSS
說明
檢查方法與類別所允許的行數(不含註解)

屬性
說明
預設值
methodMaximum
允許單一方法最多n
50
classMaximum
允許單一類別最多n
1500
範例:





檢查項目
Indentation
說明
檢查程式碼層級縮排空格數

屬性
說明
預設值
basicOffset
與上一層級應縮排的空格數
4
braceAdjustment
括號寫在下一行時應縮排空格數
0
caseIndent
使用case應縮排空格數
4
範例:

檢查項目
DeclarationOrder
說明
宣告變數的順序

屬性
說明
預設值
範例:
宣告變數時,依照public, protected, 不描述(package level), private的順序
Class宣告順序,依照static variables, instance variables, 建構子, 方法的順序

檢查項目
LineLength
說明
檢查程式一行程式碼最多的characters 

屬性
說明
預設值
max
一行程式碼最多的characters 
80
範例:

檢查項目
MultipleVariableDeclarations
說明
檢查每個變數的宣告是否自己一行,且僅宣告該變數

屬性
說明
預設值
範例:
-不好的
int x,y = 1;

-好的
int x = 1;
int y = 2;










檢查項目
GenericWhitespace
說明
檢查Generic(泛型) tokens的寫法不要存在空白

屬性
說明
預設值
範例:
-不好的
List < Integer > x = new ArrayList < Integer > ();

-好的
List x = new ArrayList();
List<String> y = new ArrayList<String>();


檢查項目
LeftCurly
說明
檢查左大括號的位置

屬性
說明
預設值
option
在一行的結尾
eol
範例:

檢查項目
ParenPad
說明
檢查左括號(之後或右括號)之前是否有空白

屬性
說明
預設值
option
不可存在空白
nospace
範例:
-不好的
pulic void test(  int a, int b  )
-好的
pulic void test(int a, int b)










檢查項目
RightCurly
說明
檢查右大括號的位置

屬性
說明
預設值
option
else, try, and catch tokens 在同一行
 same
範例:

檢查項目
MissingSwitchDefault
說明
檢查switch statement是否有”default”

屬性
說明
預設值
option


範例:

檢查項目
WhitespaceAround
說明
檢查方法與建構子的body是否為空的;
檢查token是否有空白包覆

屬性
說明
預設值
範例:
public MyClass()  {}      // empty constructor
public void func()  {}    // empty method
int  i  =  0;

-不好的
int i=0;


檢查項目
RegexpHeader
說明
檢查檔案標頭註解是否合乎規則()

屬性
說明
預設值
範例:
^/\*\*\n
^ \* 程式資訊摘要:.+\n
^ \* 類別名稱:(\w*)\.java\n
^ \* 程式內容說明:.+\n
^ \* 版本資訊:(\d+\.)?(\d+\.)?(\*|\d+)\n
^ \* 程式設計人員姓名:.+\n
^ \* 程式修改記錄:\d\d\d\d-\d\d-\d\d (.)+ (.)+\n
^ \* 版權宣告: FDC all rights reserved\.\n
^ \*/\n
package [\w\.]*;

說明:
^   一行的開始
\   跳脫字元
\n  跳新一行
.   任何單一字元
\w  letter(a-zA-Z), number(0-9), underscore(_)
*   表示任何 (\w* 表示任何字元長度的letter, number, underscore)
\d  任何數字
+   one or more (\d+ 表示1個以上的數字)
?   zero or one (\d? 表示1個或沒有數字)
|    or  (\*|\d+ 表示結果為*或者1個以上的數字)


更多可參考http://www.rubular.com/
 
 
 

沒有留言:

張貼留言