前言
推薦Google的Java編碼規範英文版:
http://google-styleguide.googlecode.com/svn/trunk/javaguide.html
雖然這篇文章的英文很簡單,但是最近發現有人翻譯了這篇文章,所以專門推薦一下:
http://hawstein.com/posts/google-java-style.html
正文
一、命名規範
已經被使用的常量,不要重新定義
約定俗成的常量含義,不要重新定義。
努力避免硬編碼。
每個模組,建議有獨立的常量類。
方法名都以lowerCamelCase風格編寫
類名都以UpperCamelCase風格編寫
引數名以lowerCamelCase風格編寫
區域性變數名以lowerCamelCase風格編寫,比起其它型別的名稱,區域性變數名可以有更為寬鬆的縮寫。
雖然縮寫更寬鬆,但還是要避免用單字元進行命名,除了臨時變數和迴圈變數。
即使區域性變數是final和不可改變的,也不應該把它示為常量,自然也不能用常量的規則去命名它。
二、函式/方法
public 函式(方法),物件引數 必須要處理引數為null的情況,
private 函式,物件引數 可以不用處理引數為null的情況(依情況而定)
方法名都以lowerCamelCase 開頭單詞小寫後面駝峰風格編寫
方法長度不超過50行
三、巢狀層級不要超過3層。
for,while,if ,switch 等。
方法中條件不成立直接return,不再向下執行
如:
public int xxx (String userId, String password, String email){
if(StringUtils.isEmpty(userId) || StringUtils.isEmpty(email)
||StringUtils.isEmpty(password)){
return null;
}
UserEntity ue = EntityProxy.OBJ.get(userId, UserEntity.class);
if(ue == null){
return null;
}
……...
}
避免前套層次過深,建議不超過三層
四、程式碼結構
1垂直
以下情況需要使用一個空行:
類內連續的成員之間:欄位,建構函式,方法,巢狀類,靜態初始化塊,例項初始化塊。
例外:兩個連續欄位之間的空行是可選的,用於欄位的空行主要用來對欄位進行邏輯分組。
在函式體內,語句的邏輯分組間使用空行。
類內的第一個成員前或最後一個成員後的空行是可選的(既不鼓勵也不反對這樣做,視個人喜好而定)。
要滿足本文件中其他節的空行要求。
多個連續的空行是允許的,但沒有必要這樣做(我們也不鼓勵這樣做)。
一個類的總體行數儘量控制在400行左右(不超過一千行)。
五、資源處理
EntityTransaction tranx = null;
try {
// 獲取資料庫事務
tranx = em.getTransaction();
// 開始事務過程
if(!tranx.isActive()){
tranx.begin();
}
// 儲存實體
Query query = em.createNamedQuery(jpqlName);
if(params!=null && !params.isEmpty()){
params.forEach((k,v)->{
query.setParameter(k, v);
});
}
query.executeUpdate();
// 提交事務
tranx.commit();
} catch (Exception ex) {
// 記錄錯誤日誌
DaoLog.LOG.error("刪除物件異常");
DaoLog.LOG.error(ex.getMessage(), ex);
if(tranx != null){
tranx.rollback();
}
return false;
}finally{
if(tranx !=null && tranx.isActive()){
tranx.commit();
}
em.close();//注意 用完一定要釋放
}
六、異常處理
比較底層的處理單元,建議丟擲異常。
業務處理模組,處理異常的同時,異常必須要加日誌!最好有finally處理。
方法返回結果,不要使用異常方式。
七、相同的程式碼快,不要到處出現或者重複出現!
相同程式碼提取處理,讓程式碼可重用。
八、註釋
1、原始檔註釋
原始檔註釋採用 /* …… /,在每個原始檔的頭部要有必要的註釋資訊,包括:檔名;檔案編號;版本號;作者;建立時間;檔案描述包括本檔案歷史修改記錄等。中文註釋模版:
/**
-
文 件 名 :
-
CopyRright (c) 2015-xxxx:
-
-
檔案編號:
-
創 建 人:
-
日 期:
-
修 改 人:
-
日 期:
-
描 述:
-
版 本 號:
*/
2、類(模組)註釋:
類(模組)註釋採用 /* …… /,在每個類(模組)的頭部要有必要的註釋資訊,包括:工程名;類(模組)編號;名稱空間;類可以執行的JDK版本;版本號;
作者;建立時間;類(模組)功能描述(如功能、主要演算法、內部各部分之間的關係、該類與其類的關係等,必要時還要有一些如特別的軟硬體要求等說明);
主要函式或過程清單及本類(模組)歷史修改記錄等。
3、介面註釋:
介面註釋採用 /* …… /,在滿足類註釋的基礎之上,介面註釋應該包含描述介面的目的、它應如何被使用以及如何不被使用,塊標記部分必須註明作者和版本。
在介面註釋清楚的前提下對應的實現類可以不加註釋。
4、建構函式註釋:
建構函式註釋採用 /* …… /,描述部分註明建構函式的作用,不一定有塊標記部分。
5、函式註釋:
函式註釋採用 /* ……/,在每個函式或者過程的前面要有必要的註釋資訊,包括:函式或過程名稱;功能描述;
輸入、輸出及返回值說明;呼叫關係及被呼叫關係說明等。函式註釋裡面可以不出現版本號(@version)。
6、方法註釋:
方法註釋採用 /* …… /,普通成員方法要求說明完成什麼功能,引數含義是什麼且返回值什麼;另外方法的建立時間必須註釋清楚,為將來的維護和閱讀提供寶貴線索。
7、方法內部註釋:
控制結構,程式碼做了些什麼以及為什麼這樣做,處理順序等,特別是複雜的邏輯處理部分,要儘可能的給出詳細的註釋。
8、全域性變數註釋:
要有較詳細的註釋,包括對其功能、取值範圍、哪些函式或者過程存取以及存取時注意事項等的說明。
9、區域性(中間)變數註釋:
主要變數必須有註釋,無特別意義的情況下可以不加註釋。
10、實參/引數註釋:
引數含義、及其它任何約束或前提條件。
十、if else 條件含義要明確
如:
if (isOk) { //isOK 如何
return Response.status(200).entity(resp.getData()).build();
} else {
return Response.status(200).entity(resp.getErrorInfo()).build();
}
十一、邏輯控制,不要瀑布流!
儘量把條件不滿足的情況寫在某個邏輯塊的前面(比如方法的最前面),讓不滿足條件的情況快速失敗,讓程式碼整理結構清晰,可讀。
十二、巧用建構函式構造者builder模式:
構造方法:UserDetailInfo userinfo = new UserDetailInfo(user);
builder方式:
Map<String, Object> oparams = ImmutableMap.<String, Object> builder()
.put("appid", ConfigUtil.APPID)// 服務號的應用號
.put("body", WeixinConstant.PRODUCT_BODY)// 商品描述
.put("mch_id", ConfigUtil.MCH_ID)// 商戶號 ?
.put("nonce_str", PayCommonUtil.CreateNoncestr())// 16隨機字串(大小寫字母加數字)
.put("out_trade_no", orderId)// 商品訂單號
.put("total_fee", "1")// 銀行幣種
.put("spbill_create_ip", ip)// IP地址
.put("notify_url", ConfigUtil.NOTIFY_URL) // 微信回撥地址
.put("trade_type", "APP")// 支付型別 app
.build();
十三、資料結構與業務處理(演算法)分開
如: MVC MVVM 都可以參考
十四、關鍵業務新增日誌記錄
LoggerUtils.loginLogger.info(String.format("xx使用者[%s] at %s 登陸xxx app", sb.toString(),DateUtils.getDateTime()));
最後囉嗦一句 :寫程式碼一個類寫完了 去掉無效的引用,也就是import的時候。
補充:養成好習慣,祝大家寫好程式碼,迎娶白富美,走上人生巔峰!
thx