阿裡巴巴Java開發手冊評

来源:https://www.cnblogs.com/jyuanhang/archive/2018/01/24/8343185.html
-Advertisement-
Play Games

2016年底的時候阿裡巴巴公開了其在內部使用的Java編程規範。隨後進行了幾次版本修訂,目前的版本為v1.0.2版。下載地址可以在其官方社區-雲棲社區https://yq.aliyun.com/articles/69327找到。 筆者作為一名有數年工作經驗的Java程式員,仔細研讀了這份手冊,覺得其 ...


 

 

 

2016年底的時候阿裡巴巴公開了其在內部使用的Java編程規範。隨後進行了幾次版本修訂,目前的版本為v1.0.2版。下載地址可以在其官方社區-雲棲社區https://yq.aliyun.com/articles/69327找到。

筆者作為一名有數年工作經驗的Java程式員,仔細研讀了這份手冊,覺得其是一份不可多得的好材料。阿裡巴巴在發佈時所說,“阿裡巴巴集團推出的《阿裡巴巴Java開發手冊(正式版)》是阿裡巴巴近萬名開發同學集體智慧的結晶,以開發視角為中心,詳細列舉如何開發更加高效、更加容錯、更加有協作性,力求知其然,更知其不然,結合正反例,讓Java開發者能夠提升協作效率、提高代碼質量。” 同時,阿裡巴巴也期望這套Java統一規範標准將有助於提高行業編碼規範化水平,幫助行業人員提高開發質量和效率、大大降低代碼維護成本。

實早在多年前,Google就已經把公司內部採用的所有語言的編碼規範(其稱為Style Guide)都開源在github上,地址為https://github.com/google/styleguide。在這份清單中,包括了C++、Objective-C、Java、[Python](Python Style Guide)、R、Shell、HTML/CSS、JavaScript、AngularJS、Common Lisp、Vimscript等語言的編程規範。並且Google還發佈了一個用於檢查樣式合規性的工具cpplint以及Emacs中使用Google編程樣式的配置文件google-c-style.el。看來Google中Emacs粉比Vim粉要強勢的多。

Google為什麼要發佈這樣的Style Guide那?因為它認為幾乎所有的開源項目都需要有一組約定來規範如何編寫代碼。如果項目中的代碼都能保持一致的風格,那麼即使代碼再多也會更容易被人理解。

Google的這份編程規範包含了很多方面,從”對變數使用camelCase命名法”到”絕不要使用全局變數”到”絕不允許例外“等。其Java編程規範包含7大部分,分別為介紹、源文件基本要求、源文件結構、格式化、命名、編程實踐和Javadoc。每一部分又細分為很多子條目。如果採取條規範的原因不是很容易理解,都會配有相應的示例或者引用文章。

由於Google的這份編程規範目前只有英文版本,所以中國的程式員只有少部分人知道它的存在。並且只有更少的團隊在真正的應用它,其中就包括我的團隊。我們團隊根據Google的Java style guide也演化出了自己的團隊版本,放置在團隊共用wiki上供大家隨時查閱。我們根據自身的項目特點豐富了"編程實踐"里的內容,並且新加入一個章節來描述編寫Java代碼的一些原則,比如簡潔代碼、組合優於繼承、stream優於for迴圈等。

我想阿裡巴巴發佈的Java開發手冊之所以叫做"開發手冊",而不是像Google那樣叫做“Style Guide(樣式風格)”,是因為它不僅僅局限於style guide這一方面,而是以Java開發者為中心視角,劃分為編程規約、異常日誌規約、MYSQL規約、工程規約、安全規約五大塊,再根據內容特征,細分成若幹二級子目錄。根據約束力強弱和故障敏感性,規約依次分為強制、推薦、參考三大類。

該開發手冊中的每一條都值得瞭解。限於篇幅原因,這裡只列出”編程規約“中有感受的幾條來評述一下。

15. 【參考】各層命名規約:

A) Service/DAO 層方法命名規約

1) 獲取單個對象的方法用 get 做首碼。

2) 獲取多個對象的方法用 list 做首碼。

3) 獲取統計值的方法用 count 做首碼。

4) 插入的方法用 save(推薦)或 insert 做首碼。

5) 刪除的方法用 remove(推薦)或 delete 做首碼。

6) 修改的方法用 update 做首碼。

B) 領域模型命名規約

1) 數據對象:xxxDO,xxx 即為數據表名。

2) 數據傳輸對象:xxxDTO,xxx 為業務領域相關的名稱。

3) 展示對象:xxxVO,xxx 一般為網頁名稱。

4) POJO 是 DO/DTO/BO/VO 的統稱,禁止命名成 xxxPOJO。

命名規約的第15條描述了在Service/DAO層對於資源的操作的命名規範。這一條的參考價值極大,因為我所有呆過的團隊對於這一點都沒有明顯的約束,每個團隊都有五花八門的實現。如果能遵守這一點,那麼我們在操作資源時就會減少一些困擾。

2. 【強制】long 或者 Long 初始賦值時,必須使用大寫的 L,不能是小寫的 l,小寫容易跟數字1混淆,造成誤解。

說明:Long a = 2l; 寫的是數字的 21,還是 Long 型的 2?

這是常量定義的第2條。從這一點可以看出阿裡巴巴對代碼可讀性的細節扣的很嚴格。我也很贊同這一點。代碼只需編寫一次,而會被查看無數次,所以要力爭在第一次編寫的時候儘可能少的引入歧義。

    1. 【強制】大括弧的使用約定。如果是大括弧內為空,則簡潔地寫成{}即可,不需要換行;如果是非空代碼塊則:

      1) 左大括弧前不換行。

      2) 左大括弧後換行。

      3) 右大括弧前換行。

      4) 右大括弧後還有 else 等代碼則不換行;表示終止右大括弧後必須換行。


      格式規約的第1條終於終結了括弧之爭。這一條需要強制遵守,那麼左大括弧換行一派則被徹底排除在阿裡巴巴之外。有人說不推薦左大括弧換行可以減少行數,增加單個屏幕可以顯示的代碼行數。而有的人反駁說現在屏幕已經足夠大,不換行則破壞了對稱之美。其實對於我來說兩種格式都有各自的好處,我都可以接受,只要團隊能夠堅持使用其中之一即可。

      5. 【強制】縮進採用 4 個空格,禁止使用 tab 字元。

       

      說明:如果使用 tab 縮進,必須設置 1 個 tab 為 4 個空格。IDEA 設置 tab 為 4 個空格時,請勿勾選 Use tab character;而在 eclipse 中,必須勾選 insert spaces for tabs。

      正例: (涉及 1-5 點)

使用空格代替tab字元進行縮進已經成為了編程界的共識。其主要原因是不同的平臺甚至不同的編輯器下tab字元的長短是不一樣的。不過Google在其《java style guide》中規定縮進為2個空格,而阿裡巴巴約定為4個空格。由於4個空格的縮進比2個空格的縮進長一倍,所以如果在代碼嵌套過深的情況下可能會很快超過單行最多字元數(阿裡巴巴規定為120個)的限制。不過這個問題可以從另一個方面進行思考,如果由於縮進的原因導致單行字元數超標,這很可能是代碼設計上有壞味道而導致嵌套過深。所以最好應該從調整代碼結構的方面下手。

6. 【強制】單行字元數限制不超過 120 個,超出需要換行,換行時遵循如下原則:

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

2) 運算符與下文一起換行。

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

4) 在多個參數超長,逗號後進行換行。

5) 在括弧前不要換行,見反例。

正例:

反例:

 

 

關於換行Google並沒有給出明確的要求,而阿裡巴巴則給出了強制性的要求。Google特別提示通過一些重構手法可以減少單行字元長度從而避免換行,這一點我頗為認同。關於參數很多的方法調用超過120個字元需要換行時,這暴露除了過長參數列的代碼壞味道,解決方式之一就是使用重構手法的Replace Parameter With Method的方式把一次方法調用化為多次方法調用,或者使用Introduce Parameter Object手法創造出參數對象併進行傳遞。

17. 【推薦】迴圈體內,字元串的聯接方式,使用 StringBuilder 的 append 方法進行擴展。

反例:

說明:反編譯出的位元組碼文件顯示每次迴圈都會 new 出一個 StringBuilder 對象,然後進行append 操作,最後通過 toString 方法返回 String 對象,造成記憶體資源浪費。

這是《Effective Java》以及其他文章中經常提及的優化方式,而且面試初級Java工程師時幾乎是一個必考點。其實不僅是在迴圈體內,而是所有需要進行多次字元串拼接的地方都應該使用StringBuilder對象。

20. 【推薦】類成員與方法訪問控制從嚴:

1) 如果不允許外部直接通過 new 來創建對象,那麼構造方法必須是 private。

2) 工具類不允許有 public 或 default 構造方法。

3) 類非 static 成員變數並且與子類共用,必須是 protected。

4) 類非 static 成員變數並且僅在本類使用,必須是 private。

5) 類 static 成員變數如果僅在本類使用,必須是 private。

6) 若是 static 成員變數,必須考慮是否為 final。

7) 類成員方法只供類內部調用,必須是 private。

8) 類成員方法只對繼承類公開,那麼限製為 protected。

說明:任何類、方法、參數、變數,嚴控訪問範圍。過寬泛的訪問範圍,不利於模塊解耦。思考:如果是一個 private 的方法,想刪除就刪除,可是一個 public 的 Service 方法,或者一個 public 的成員變數,刪除一下,不得手心冒點汗嗎?變數像自己的小孩,儘量在自己的視線內,變數作用域太大,如果無限制的到處跑,那麼你會擔心的。

這其實就是經典的原則‘

Principle of least privilege’ 的體現。我們必須遵循這一原則,但不知為何阿裡巴巴將其級別列為“推薦”。

7. 【參考】方法中需要進行參數校驗的場景:

1) 調用頻次低的方法。

2) 執行時間開銷很大的方法,參數校驗時間幾乎可以忽略不計,但如果因為參數錯誤導致

中間執行回退,或者錯誤,那得不償失。

3) 需要極高穩定性和可用性的方法。

4) 對外ᨀ供的開放介面,不管是 RPC/API/HTTP 介面。

5) 敏感許可權入口。

8. 【參考】方法中不需要參數校驗的場景:

1) 極有可能被迴圈調用的方法,不建議對參數進行校驗。但在方法說明裡必須註明外部參

數檢查。

 

2) 底層的方法調用頻度都比較高,一般不校驗。畢竟是像純凈水過濾的最後一道,參數錯

誤不太可能到底層才會暴露問題。一般 DAO 層與 Service 層都在同一個應用中,部署在同一

台伺服器中,所以 DAO 的參數校驗,可以省略。

3) 被聲明成 private 只會被自己代碼所調用的方法,如果能夠確定調用方法的代碼傳入參

數已經做過檢查或者肯定不會有問題,此時可以不校驗參數。

編寫代碼時,對參數進行校驗是不可避免的。詳細說又扯到“防禦式編程”和“契約式編程”的話題上。這兩項之所以列為參考,並沒有強迫大家遵守。

6. 【推薦】與其“半吊子”英文來註釋,不如用中文註釋把問題說清楚。專有名詞與關鍵字保持英文原文即可。

反例:“TCP 連接超時”解釋成“傳輸控制協議連接超時”,理解反而費腦筋。看到這一條我已經笑出來了。這一條說的很好,註釋是用來闡述問題的,如果看了註釋還一頭霧水,那麼這樣的註釋不要也罷。使用中文沒什麼可丟人的,解決問題才是王道。

7. 【推薦】代碼修改的同時,註釋也要進行相應的修改,尤其是參數、返回值、異常、核心邏輯等的修改。

說明:代碼與註釋更新不同步,就像路網與導航軟體更新不同步一樣,如果導航軟體嚴重滯後,

就失去了導航的意義。

阿裡巴巴對該條的說明非常到位。其實我們團隊在編寫代碼時預設是沒有任何註釋的,因為我們追求的是self-explanatory methods。即代碼本身已經就能說明它的用途。只有在很少的情況下需要添加註釋。

編程規約的第九部分都是很好的tips,值得去瞭解和學習。

除了編程規約之外,日誌規約、MySQL規約、工程規約和安全規約也都有極高的參考價值,這也是比Google的Java Style Guide出色的地方。這裡就不再評述了。

阿裡巴巴公佈這個Java開發手冊絕對是值得贊賞的事情。最後我也想給其提幾點建議:

  1. 建議使用公開wiki的方式發佈該手冊,而不是採用pdf的方式。因為如果像google那樣是公開wiki的方式的話,可以很方便大家參與修正和改進,並且可以看到版本歷史。

  2. 該手冊並沒有明確的版權許可,只是在頁腳處加入了“禁止用於商業用途,違者必究”的字樣。Google的style guide的版權為CC-By 3.0 License,建議阿裡巴巴能夠指明其版權。

手冊中的部分示例代碼並沒有遵守其列出的編程規約,有點打臉之嫌。比如以下示例代碼:

其while和if關鍵字與小括弧之間並沒有空格,違反了該手冊中3. 【強制】if/for/while/switch/do 等保留字與左右括弧之間都必須加空格。這一規則

4.處理中可以多推薦一些Java8的集合操作方法。

5.有些名詞沒有過多解釋,比如很多人可能都不知道什麼叫一方庫、二方庫。

6.除了這份開發手冊以外,阿裡巴巴也可以推出對應的checkstyle配置文件以及Intellij、Eclipse的配置文件。畢竟格式化這些事都可以交由IDE來解決,通過在構建時使用checkstyle插件也可以防止不合規的代碼遷入到倉庫,從源頭上保證代碼樣式的一致性。

最後,希望這份Java開發手冊可以持續改進,吸納百家之長,成為每個入門程式員必看的手冊。

**如果你想學習Java工程化、高性能及分散式、高性能、深入淺出。性能調優、Spring,MyBatis,Netty源碼分析和大數據等知識點可以來找我。

而現在我就有一個平臺可以提供給你們學習,讓你在實踐中積累經驗掌握原理。主要方向是JAVA架構師。如果你想拿高薪,想突破瓶頸,想跟別人競爭能取得優勢的,想進BAT但是有擔心面試不過的,可以加我的Java架構進階群:697579751

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • package com.swift; public class TotalNumber_String { public static void main(String[] args) { /* * 如果一串字元如"aaaabbc中國1512"要分別統計英文字元的數量,中文字元的數量,和數字字元的數量... ...
  • http://blog.csdn.net/u011475134/article/details/70198533 原出處 在上一篇文章《使用python-aiohttp爬取網易雲音樂》中,我們給自己的微信公眾號添加了線上點歌的功能,這次我們再增加一個新聞瀏覽的功能。由於我平時瀏覽新聞用的是今日頭條, ...
  • 1、<?php echo count(strlen(“http://php.net”)); ?>的執行結果是? 答案:1 講解:count(var)是用來統計數組或對象的元素個數的。當var是null或者空數組時,結果為0。如果var是普通變數,則返回1。正常情況下返回var中的元素或屬性個數。 2 ...
  • 按鍵值的降序排序 按值的降序排序,如果值相同則按鍵值的字母順序 要註意這個問題: 不能把map.entrySet()直接強轉成List<Entry<Character,Integer>> 需要用new ArrayList()的構造,即放在參數中 ...
  • 不想下班之後待在只有自己一個人的小房間了自怨自艾,懷疑人生。所以,我選擇python 為什麼是它? 有過那麼一段想法,哈哈哈哈哈哈哈額。。。世界沒後悔藥吃,現在也不遲。保持前進就好。 給自己兩年時間。 為什麼是兩年? 有時間限制,會更有動力。 你拿什麼跟別人電腦基礎良好,大學專業課程四年的人比? ...
  • 獻上代碼,不成敬意: ~~~~ include include int main() { int i = 0; if(fork()) i++; if(fork()) i++; if(fork()) i++; printf("i = %d\n",i); return 0; } ~~~~ 一段看似簡單但 ...
  • 今天正在看書,老鐵給我發來一道面試題。 初看這道題,我覺得是送分題。嘴角上揚寫出一行命令: 仔細看了一眼,這道題說的是將字元刪掉,好險中了他的招,然後改了一下。 看了一下,沒毛病,遂發給老鐵,老鐵瞬即回覆:非也,非也。這種難度豈敢請教愚兄。此題有陷阱,若是生成列表推導或是生成器表達式抑或是map,f ...
  • 元組(tuple):戴上了枷鎖的列表 元組與列表非常相似但是元組內元素的類型相同,且元組內的元素不能修改 1、創建元組的方法 與列表不同創建元組大部分情況下是用小括弧,例如 也可以不用小括弧,例如 因此創建元組的關鍵在於“逗號”,在創建單個元素的元組時應註意: >>> 8*8,(64,)>>> 8* ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...