阿里巴巴 Java 代碼規範

1. 抽象類命名使用 Abstratc開頭。html

2. 阿里強制規定不容許任何魔法值(未經定義的常量)直接出如今代碼中。魔法值會讓代碼的可讀性大大下降,並且若是一樣的數值屢次出現時,容易出現不清楚這些數值是否表明一樣的java

    含義。另外一方面,若是原本應該使用相同的數值,一旦用錯,也難以發現。所以能夠採用如下兩點,極力避免使用魔法數值。算法

3. 阿里推薦若是變量值僅在一個範圍內變化,且帶有名稱以外的延伸屬性,定義爲枚舉類。對於固定而且編譯時對象,如 Status、Type 等,應該採用 enum 而非自定義常量實現,enum 的編程

     好處是類型更清楚,不會再編譯時混淆。這是一個建議性的試用推薦,枚舉可讓開發者在 IDE 下使用更方便,也更安全。另外就是枚舉類型是一種具備特殊約束的類類型,這些約束的數組

     存在使得枚舉類自己更加簡潔、安全、便捷。安全

4. 阿里強制規定若是是大括號爲空,則簡潔地寫成{}便可,不須要換行服務器

5. 阿里強制規定單行字符數限制不超過 120 個,超出須要換行,換行時遵循以下原則:數據結構

    1).第二行相對第一行縮進 4 個空格,從第三行開始,再也不繼續縮進,參考示例。併發

    2).運算符與下文一塊兒換行。app

    3).方法調用的點符號與下文一塊兒換行。

    4).方法調用時,多個參數,須要換行時,在逗號後進行。

    5).在括號前不要換行

6. 阿里強制規定代碼中避免經過一個類的對象引用訪問此類的靜態變量或靜態方法,暫時無謂增長編譯器解析成本,直接用類名來訪問便可。

    爲何須要這樣作呢?由於被 static 修飾過的變量或者方法都是隨着類的初始化產生的,在堆內存中有一塊專門的區域用來存放,後續直接用類名訪問便可,避免編譯成本的增長和實例

     對象存放空間的浪費。

     StackOverflow 上也有人提出了相同的疑問,網友較爲精闢的回覆是"這是因爲生命週期決定的,靜態方法或者靜態變量不是以實例爲基準的,而是以類爲基準,因此直接用類訪問,不然

      違背了設計初衷"。那爲何還保留了實例的訪問方式呢?多是由於容許應用方無污染修改吧。

7. 阿里強制規定相同參數類型、相同業務類型,纔可使用 Java 的可變參數,避免使用 Object,而且要求可變參數必須放置在參數列表的最後(提倡同窗們儘可能不用可變參數編程)。

    擁有可變參數的方法能夠被重載,在被調用時,若是能匹配到參數定長的方法則優先調用參數定長的方法。

8.單例模式:

    1).雙檢查鎖機制(Double Check Locking),這裏在聲明變量時使用了 volatile 關鍵字來保證其線程間的可見性;在同步代碼塊中使用二次檢查,以保證其不被重複實例化。

         集合其兩者,這種實現方式既保證了其高效性,也保證了其線程安全性。

    2).懶漢式: 

9. 阿里強制規定在一個 switch 塊內,每一個 case 要麼經過 break/return 等來終止,要麼註釋說明程序將繼續執行到哪個 case 爲止;在一個 switch 塊內,都必須包含一個 default 

    語句而且放在最後,即便它什麼代碼也沒有。語法上來講,default 語句中的 break 是多餘的,可是若是後續添加額外的 case,能夠避免找不到匹配 case 項的錯誤。

10. 阿里強制規定使用集合轉數組的方法,必須使用集合的 toArray(T[] arrays),傳入的是類型徹底同樣的數組,大小就是 list.size()。使用 toArray 帶參方法,入參分配的數組空間不夠大時,

      toArray 方法內部將從新分配內存空間,並返回新數組地址;若是數組元素大於實際所需,下標爲[list.size()]的數組元素將被置爲 null,其它數組元素保持原值,所以最好將方法入參數組大小定義與集合元素個數一致。

      String[] array = new String[list.size()]; 

      array = list.toArray(array);

11. 阿里強制要求方法內部單行註釋,在被註釋語句上方另起一行,使用//註釋。方法內部多行註釋使用/**/註釋,注意與代碼對照。

      百度規定方法註釋採用標準的 Javadoc 註釋規範,註釋中必須提供方法說明、參數說明及返回值和異常說明。騰訊規定採用 JavaDoc 文檔註釋,在方法定義以前應該對其進行註釋,

       包括方法的描述、輸入、輸出以及返回值說明、拋出異常說明、參考連接等。

12. 不帶參數的 toArray()構造一個 Object 數組,而後進行數據拷貝

13. 阿里推薦任何數據結構的構造或初始化,都應指定大小,避免數據結構暫時無限增加吃光內存。

      首先明確一點,阿里這裏指的大小具體是指數據結構的最大長度。大部分 Java 集合類在構造時指定的大小都是初始尺寸(initial Capacity),而不是尺寸上限(Capacity),只有幾

      種隊列除外,例如 ArrayBlockingQueue、LinkedBlockingQueue,它們在構造時能夠指定隊列的最大長度。阿里推薦的目的是爲了合理規劃內存,避免出現 OOM(Out of Memory)異常。

14. 阿里強制規定 Java 類庫中的 RuntimeException 能夠經過預先檢查進行規避,而不該該經過 catch 來處理,例如 IndexOutOfBoundsException、NullPointerException 等。

      RuntimeException,也被稱爲運行時異常,一般是因爲代碼中的 bug 引發的,正確的處理方式是去檢查代碼,經過添加數據長度判斷,判斷對象是否爲空等方法區規避,而不是靠捕獲來規避這種異常。

15. 阿里強制規定有 try 塊放到了事務代碼中,catch 異常後,若是須要回滾事務,必定要注意手動回滾事務。

      try catch 代碼塊中對異常的處理,可能會遺漏事務的一致性,當事務控制不使用其餘框架管理時,事務須要手動回滾。實際使用若是引入第三方的框架對事務進行管理,好比 Spring,則根據第三方

      框架的實際實現狀況,肯定是否有必要手動回滾。當第三方事務管理框架自己就會對於異常進行拋出時須要作事務回滾。例如 Spring 在@Transactional 的 annotation 註解下,會默認開啓運行時異常事務回滾。

16. 阿里強制規定應用中不可直接使用日誌系統(Log4j、Logback)中的 API,而應依賴使用日誌框架 SLF4J 中的 API,使用門面模式的日誌框架,有利於維護和各個類的日誌處理方式統一。

17. 阿里強制規定日誌文件至少保存 15 天,由於有些異常具有以"周"爲頻次發生的特色。

      日誌保留時間推薦 15 天以上,可是保留時間也不宜過長,通常不超過 21 天,不然形成硬盤空間的浪費。對於一些長週期性執行的邏輯,能夠根據實際狀況調整該保存時間,同時也

      須要保證日誌可以監控到關鍵的應用。

      對於長週期執行的邏輯,可使用特定的 appender,並使用不一樣的日誌清理規則,如時間、大小等。如一月執行一次的定時任務,能夠將日誌輸出到新的日誌文件,而後經過大小限定

      的規則進行清理,並不必定要使用時間清理的邏輯。 

18. 阿里強制要求對於隸屬於用戶我的的頁面或者功能必須進行權限控制校驗。

      涉及到對於數據的增刪改查,必須有權限的控制和校驗,要有一個黑白名單的控制,不能依賴於前臺頁面的簡單控制,後臺要有對於完整的權限控制的實現。這樣就能儘量地防治數據的錯誤修改。

19. 阿里強制要求用戶請求傳入的任何參數必須作有效校驗。

20.單元測試:

     1). 單元測試應該自動執行:阿里強制單元測試應該是全自動執行的,而且非交互式的。測試框架一般是按期執行的,執行過程必須徹底自動化纔有意義。輸出結果須要人工檢查的測試

          不是一個號的單元測試。單元測試中不許使用 System.out 來進行人肉驗證,必須使用 assert 來驗證。 

     2). 單元測試應該是獨立的:阿里強制保持單元測試的獨立性。爲了保證單元測試穩定可靠且便於維護,單元測試用例之間決不能互相調用,也不能依賴執行的前後次序。反例:method2 

          須要依賴 method1 的執行,將執行結果做爲 method2 的輸入。

          編寫單元測試時遇到的這類依賴可使用 mock 來模擬輸入和指望的返回,這樣因此來的方法內部邏輯的變動就不會影響到外部的實現。

      3).阿里推薦編寫單元測試代碼遵照 BCDE 原則,以保證被測試模塊的交付質量。

          a). B(Border):確保參數邊界值均被覆蓋。例如:對於數字,測試負數、0、正數、最小值、最大值、NaN(非數字)、無窮大值等。對於字符串,測試空字符串、單字符、

               非 ASCII 字符串、多字節字符串等。對於集合類型,測試空、第一個元素、最後一個元素等。對於日期,測試 1 月 1 日、2 月 29 日、12 月 31 日等。被測試的類自己

               也會暗示一些特定狀況下的邊界值。對於邊界狀況的測試必定要詳盡。

          b). C(Connect):確保輸入和輸出的正確關聯性。例如,測試某個時間判斷的方法 boolean inTimeZone(Long timeStamp),該方法根據輸入的時間戳判斷該事件是否存在於某個

               時間段內,返回 boolean 類型。若是測試輸入的測試數據爲 Long 類型的時間戳,對於輸出的判斷應該是對於 boolean 類型的處理。若是測試輸入的測試數據爲非 Long 類型

               數據,對於輸出的判斷應該是報錯信息是否正確。

          c).D(Design):任務程序的開發包括單元測試都應該遵循設計文檔。

          d).E(Error):單元測試包括對各類方法的異常測試,測試程序對異常的響應能力。 

21.《單元測試之道(Java 版)》這本書裏面提到了關於邊界測試的 CORRECT 原則:

       1).一致性(Conformance):值是否符合預期格式(正常的數據),列出全部可能不一致的數據,進行驗證。

       2).有序性(Ordering):傳入的參數的順序不一樣的結果是否正確,對排序算法會產生影響,或者是對類的屬性賦值順序不一樣會不會產生錯誤。

       3).區間性(Range):參數的取值範圍是否在某個合理的區間範圍內。

       4).引用/耦合性(Reference):程序依賴外部的一些條件是否已知足。前置條件:系統必須處於什麼狀態下,該方法才能運行。後置條件,你的方法將會保證哪些狀態發生改變。

       5).存在性(Existence):參數是否真的存在,引用爲 Null,String 爲空,數值爲 0 或者物理介質不存在時,程序是否能正常運行。

       6).基數性(Cardinality):考慮以"0-1-N 原則",當數值分別爲 0、一、N 時,可能出現的結果,其中 N 爲最大值。

       7).時間性(Time):相對時間指的是函數執行的依賴順序,絕對時間指的是超時問題、併發問題。

22. 阿里強制要求若是遇到須要表達是與否的概念時,必須使用 is_xxx 的方法命令,數據類型是 unsigned tinyint,1 表示是,0 表示否。

      說明:任務字段若是爲非負數,必須是 unsigned。 

      命名使用 is_xxx 第一個好處是比較清晰的,第二個好處是使用者根據命名就能夠知道這個字段的取值範圍,也方便作參數驗證。類型使用 unsigned 的好處是若是隻存整數,

       unsigned 類型有更大的取值範圍,能夠節約磁盤和內存使用。

23. 對於表的名字,MySQL 社區有本身推薦的命名規範:

      1).表包含多個英文單詞時,須要用下劃線進行單詞分割,這一點相似於 Java 類名的命名規範,例如 master_schedule、security_user_permission;

      2).因爲 InnoDB 存儲引擎自己是針對操做系統的可插拔設計的,因此原則上全部的表名組成所有由小寫字母組成;

      3).不容許出現空格,須要分割一概採用下劃線;

      4).名字不容許出現數字,僅包含英文字母;

      5).名字須要總長度少於 64 個字符。 

24. 數據類型精度考量:阿里強制要求存放小數時使用 decimal,禁止使用 float 和 double。

      說明:float 和 double 在存儲的時候,存在精度損失的問題,極可能在值的比較時,獲得不正確的結果。若是存儲的數據範圍超過 decimal 的範圍,建議將數據拆成整數和小數分開存儲。

      實際上,全部涉及到數據存儲的類型定義,都會涉及數據精度損失問題。Java 的數據類型也存在 float 和 double 精度損失狀況,阿里沒有指出這條規約,就全文來講,這是一個比較嚴重的規約缺失。

25. 採用 BigDecimal 有一個缺點,就是使用過程當中沒有原始數據這麼方便,效率也不高。若是採用 int 方式,最好不要在有小數點的場景下使用,能夠在 100、10 這樣業務場景下選擇使用。

26. 阿里強制要求若是存儲的字符串長度幾乎相等,使用 Char 定長字符串類型。

27. 服務間依賴關係:阿里推薦默認上層依賴於下層,箭頭關係表示可直接依賴,如:開放接口層能夠依賴於 Web 層,也能夠直接依賴於 Service 層。 

28. 阿里推薦高併發服務器建議調小 TCP 協議的 time_wait 超時時間。

      說明:操做系統默認 240 秒後纔會關閉處於 time_wait 狀態的鏈接,在高併發訪問下,服務器端會由於處於 time_wait 的鏈接數太多,可能沒法創建新的鏈接,因此須要在服務器上調小此等待值。

      正例:在 Linux 服務器上經過變動/etc/sysctl.conf 文件去修改該缺省值(秒):net.ipv4.tcp_fin_timeout=30

 

參見:https://www.ibm.com/developerworks/cn/java/deconding-code-specification-part-1/index.html

         https://www.ibm.com/developerworks/cn/java/deconding-code-specification-part-2/index.html?ca=drs-

相關文章
相關標籤/搜索