下載原版阿里JAVA開發手冊 【阿里巴巴Java開發手冊v1.2.0】
本文主要是對照阿里開發手冊,注釋自己在工作中運用情況。
本文內容:異常處理 日志規約
本文難度系數為一星(★) 本文為第三篇
第一篇 點評阿里JAVA手冊之編程規約(命名風格、常量定義、代碼風格、控制語句、注釋規約)
第二篇 點評阿里JAVA手冊之編程規約(OOP 規約 、集合處理 、並發處理 、其他)
第三篇 點評阿里JAVA手冊之異常日志(異常處理 日志規約 )
第四篇 點評阿里JAVA手冊之MySQL數據庫 (建表規約、索引規約、SQL語句、ORM映射)
碼出高效、碼出質量。
代碼的字里行間流淌的是軟件生命中的血液,質量的提升是盡可能少踩坑,杜絕踩重復的坑,切實提升質量意識。另外,現代軟件架構都需要協同開發完成,高效協作即降低協同成本,提升溝通效率,所謂無規矩不成方圓,無規范不能協作。眾所周知,制訂交通法規表面上是要限制行車權,實際上是保障公眾的人身安全。試想如果沒有限速,沒有紅綠燈,誰還敢上路行駛。對軟件來說,適當的規范和標准絕不是消滅代碼內容的創造性、優雅性,而是限制過度個性化,以一種普遍認可的統一方式一起做事,提升協作效率。
異常日志
(一) 異常處理
1. 【強制】Java 類庫中定義的一類RuntimeException 可以通過預先檢查進行規避,而不應該通過 catch 來處理,
比如:IndexOutOfBoundsException,NullPointerException 等等。 說明:無法通過預檢查的異常除外,如在解析一個外部傳來的字符串形式數字時,
通過 catch NumberFormatException 來實現。
正例:if (obj != null) {...}
反例:try { obj.method() } catch (NullPointerException e) {...}
【點評】規則好,嚴格遵循。
2. 【強制】異常不要用來做流程控制,條件控制,因為異常的處理效率比條件分支低。
【點評】規則好,嚴格遵循。
3. 【強制】對大段代碼進行 try-catch,這是不負責任的表現。catch 時請分清穩定代碼和非穩 定代碼,穩定代碼指的是無論如何不會出錯的代碼。
對於非穩定代碼的 catch 盡可能進行區分 異常類型,再做對應的異常處理。
【點評】規則好,嚴格遵循。
4. 【強制】捕獲異常是為了處理它,不要捕獲了卻什么都不處理而拋棄之,如果不想處理它,請將該異常拋給它的調用者。
最外層的業務使用者,必須處理異常,將其轉化為用戶可以理解的內容。
【點評】規則好,嚴格遵循。
5. 【強制】有 try 塊放到了事務代碼中,catch 異常后,如果需要回滾事務,一定要注意手動回滾事務。
【點評】規則好,嚴格遵循。
6. 【強制】finally 塊必須對資源對象、流對象進行關閉,有異常也要做 try-catch。
說明:如果 JDK7 及以上,可以使用 try-with-resources 方式。
【點評】規則好,嚴格遵循。
7. 【強制】不能在 finally 塊中使用 return,finally 塊中的 return 返回后方法結束執行,不會再執行 try 塊中的 return 語句。
【點評】規則好,嚴格遵循。
8. 【強制】捕獲異常與拋異常,必須是完全匹配,或者捕獲異常是拋異常的父類。
說明:如果預期對方拋的是綉球,實際接到的是鉛球,就會產生意外情況。
【點評】規則好,嚴格遵循。
9. 【推薦】方法的返回值可以為 null,不強制返回空集合,或者空對象等,必須添加注釋充分
說明什么情況下會返回 null 值。調用方需要進行 null 判斷防止 NPE 問題。
說明:本手冊明確防止 NPE 是調用者的責任。即使被調用方法返回空集合或者空對象,對調用者來說,也並非高枕無憂,必須考慮到遠程調用失敗、序列化失敗、運行時異常等場景返回 null 的情況。
【點評】規則好,嚴格遵循。解答了在編程中的疑問
10. 【推薦】防止 NPE(),是程序員的基本修養,注意 NPE 產生的場景:
1)返回類型為基本數據類型,return 包裝數據類型的對象時,自動拆箱有可能產生 NPE。 反例:public int f() { return Integer 對象}, 如果為 null,自動解箱拋 NPE。
2)數據庫的查詢結果可能為 null。
3)集合里的元素即使 isNotEmpty,取出的數據元素也可能為 null。
4)遠程調用返回對象時,一律要求進行空指針判斷,防止 NPE。
5)對於 Session 中獲取的數據,建議 NPE 檢查,避免空指針。
6)級聯調用 obj.getA().getB().getC();一連串調用,易產生 NPE。
正例:使用 JDK8 的 Optional 類來防止 NPE 問題。
【點評】規則好,嚴格遵循
11. 【推薦】定義時區分 unchecked / checked 異常,避免直接拋出 new RuntimeException(),更不允許拋出 Exception 或者 Throwable,
應使用有業務含義的自定義異常。
推薦業界已定義過的自定義異常,如:DAOException / ServiceException 等。
【點評】規則好,嚴格遵循
12. 【參考】在代碼中使用“拋異常”還是“返回錯誤碼”,對於公司外的 http/api 開放接口必須使用“錯誤碼”;
而應用內部推薦異常拋出;跨應用間 RPC 調用優先考慮使用 Result 方式,封裝 isSuccess()方法、“錯誤碼”、“錯誤簡短信息”。
說明:關於 RPC 方法返回方式使用 Result 方式的理由:
1)使用拋異常返回方式,調用方如果沒有捕獲到就會產生運行時錯誤。
2)如果不加棧信息,只是 new 自定義異常,加入自己的理解的 error message,對於調用 端解決問題的幫助不會太多。如果加了棧信息,在頻繁調用出錯的情況下,數據序列化和傳輸 的性能損耗也是問題。
【點評】規則好,嚴格遵循
13. 【參考】避免出現重復的代碼(Don’t Repeat Yourself),即 DRY 原則。
說明:隨意復制和粘貼代碼,必然會導致代碼的重復,在以后需要修改時,需要修改所有的副本,容易遺漏。
必要時抽取共性方法,或者抽象公共類,甚至是共用模塊。
正例:一個類中有多個 public 方法,都需要進行數行相同的參數校驗操作,這個時候請抽取:
private boolean checkParam(DTO dto) {...}
【點評】規則好,嚴格遵循
(二) 日志規約
1. 【強制】應用中不可直接使用日志系統(Log4j、Logback)中的 API,而應依賴使用日志框架 SLF4J 中的 API,使用門面模式的日志框架,
有利於維護和各個類的日志處理方式統一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
【點評】規則好,未嚴格遵循
2. 【強制】日志文件推薦至少保存 15 天,因為有些異常具備以“周”為頻次發生的特點。
【點評】規則好,嚴格遵循
3. 【強制】應用中的擴展日志(如打點、臨時監控、訪問日志等)命名方式: appName_logType_logName.log。
logType:日志類型,推薦分類有 stats/desc/monitor/visit 等;
logName:日志描述。這種命名的好處:通過文件名就可知 道日志文件屬於什么應用,什么類型,什么目的,也有利於歸類查找。 正例:mppserver 應用中單獨監控時區轉換異常,如: mppserver_monitor_timeZoneConvert.log
說明:推薦對日志進行分類,如將錯誤日志和業務日志分開存放,便於開發人員查看,也便於通過日志對系統進行及時監控。
【點評】規則好,未嚴格遵循
4. 【強制】對 trace/debug/info 級別的日志輸出,必須使用條件輸出形式或者使用占位符的方式。
說明:logger.debug("Processing trade with id: " + id + " symbol: " + symbol); 如果日志級別是 warn,上述日志不會打印,但是會執行字符串拼接操作,如果 symbol 是對象, 會執行 toString()方法,浪費了系統資源,執行了上述操作,最終日志卻沒有打印。
正例:(條件) if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " symbol: " + symbol); }
正例:(占位符) logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
【點評】規則好,嚴格遵循
5. 【強制】避免重復打印日志,浪費磁盤空間,務必在 log4j.xml 中設置 additivity=false。
正例:<logger name="com.taobao.dubbo.config" additivity="false">
【點評】規則好,未嚴格遵循
6. 【強制】異常信息應該包括兩類信息:案發現場信息和異常堆棧信息。如果不處理,那么通過關鍵字 throws 往上拋出。
正例:logger.error(各類參數或者對象 toString + "_" + e.getMessage(), e);
【點評】規則好,嚴格遵循
7. 【推薦】謹慎地記錄日志。生產環境禁止輸出 debug 日志;有選擇地輸出 info 日志;
如果使用 warn 來記錄剛上線時的業務行為信息,一定要注意日志輸出量的問題,避免把服務器磁盤 撐爆,並記得及時刪除這些觀察日志。
說明:大量地輸出無效日志,不利於系統性能提升,也不利於快速定位錯誤點。
記錄日志時請思考:這些日志真的有人看嗎?看到這條日志你能做什么?
能不能給問題排查帶來好處?
【點評】規則好,【生產環境禁止輸出 debug 日志】。嚴格遵循。這必須這個需要想想
8. 【參考】可以使用 warn 日志級別來記錄用戶輸入參數錯誤的情況,避免用戶投訴時,無所適從。
注意日志輸出的級別,error 級別只記錄系統邏輯出錯、異常等重要的錯誤信息。
如非必要,請不要在此場景打出 error 級別。
【點評】規則好,嚴格遵循