自己整理的java程式設計規範

Kevin發表於2016-06-05

前言

推薦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

相關文章