有人說「Well, an exception is a goto.」,但也有人言「makes the code simpler by visibly separating the general case of expected processing from the special cases of errors.」spring
簡單地分析一下二者優劣。異常的優勢:讓代碼更簡潔,再也不處處if-return;不管CheckedEx仍是UnCheckEx都會強迫調用方或系統處理;Exception Chain和繼承體系,能夠解耦檢測錯誤和錯誤處理,方便包裝異常和控制錯誤鏈;異常調試方便,能夠跟蹤到引起異常的源指令。異常的缺點,除了效率慢以外,最重要的一點是很難知道應該try-catch具體神馬。例:apache
badly exception-based exception安全
not badly exception-based exception框架
很難發現由於先初始化Visible=true、在new Icon時拋異常致使錯誤邏輯的情景。但對於ErrorCode而言,因爲大量的if-return、更容易辨識邏輯的正確性。函數
ErrorCode的優勢在於清楚每個具體的錯誤類型Code,但你必定不清楚可能捕獲多少具體Exception;返回一種結果狀態,如0〜成功、-1〜失敗;將Error的傳播層限制在父層,對於Exception Chain而言,「The thrower of an exception is specifically relinquishing the right to have any expectations about how the exception will be handled.」;易於CodeReview以及保證編寫邏輯正確性,被用於編寫操做系統、底層驅動等等。但有許多缺點,沒有像Exception的鏈式處理等諸多優勢,並且常常忘記檢測返回是否成功、須要頻繁變動ErrorCode等數據類型。ui
對於Exception和ErrorCode而言,須要找到二者的平衡點,有如下一些原則:this
一、對於絕大部分代碼而言,Exception更加安全,到少會有異常體系去處理,再不濟也就程序異常 終止;但針對須要well-reviewed的關鍵代碼,適宜採用ErrorCode;google
二、若是涉及到與業務邏輯相關的代碼,最好採用ErrorCode;業務邏輯無關的代碼,如傳入參數校驗,採用Exception;spa
三、除了trying以外沒有處理邏輯和更多優點的狀況,最好採用Exception;操作系統
四、遠程接口實現中,僅採用ErrorCode。由於遠程調用框架對Exception的支持度等具備較大差別。
僅當涉及到業務邏輯錯誤的狀況下拋出異常,注意幾點:
一、一個系統中至多有3〜5個具體自定義異常,如ibatis就僅5個左右;
二、若是Caller負責在調用以前檢測條件,則應該拋出UnCheckedEx,不然拋出CheckedEx;
三、遠程調用必定要try-catch;
四、ErrorCode應該採用Code+String形式,如:
五、return ErrorCode應當採用「{object, error}」的形式,如:
e.g:一個異常體系設計示例
參數校驗,是一類比較容易觸發返回ErrorCode或拋Exception的行爲。有類規則:
一、Api入參校驗採用Exception方式;
二、容許出錯的參數校驗、採用ErrorCode方式。
參數校驗有幾類經常使用包,如:
com.google.common.base.Preconditions
org.springframework.validation.ValidationUtils
org.apache.commons.lang.Validate
不太推薦使用Spring的ValidationUtils,太過依賴Spring框架、向後擴展性不強。Guava庫的Preconditions vs. Apache的Validate:
一、Preconditions校驗可拋出不一樣異常,如checkArgument throws IllegalArgumentException、checkNotNull throws NullPointerException等,Validate則僅拋出一種IllegalArgumentException;
二、Message參數,Preconditions適爲靈活,Validate不支持StringFormat,如:
Validate.isTrue(i > 0, "Should be positive but was: " + i);
Validate.isTrue(i > 0, "Should be positive but was: ", i);
checkArgument(i > MIN, "Expected more than %s, got %s", MIN, i);
三、集合判斷,Apache有幾個額外的函數:
Validate.notEmpty(Collection collection)
Validate.notEmpty(Map map)
Validate.notEmpty(Object[] array)
Validate.noNullElements(Collection collection)
Validate.noNullElements(Object[] array)
而Precondictions使用則比較麻煩:checkArgument(isNotEmpty(list));
四、Precondictions能夠一條語句搞定判斷後賦值,this.field = checkNotNull(parameter);
五、比較陳舊的系統,推薦使用Validate;
http://c2.com/cgi/wiki?AvoidExceptionsWheneverPossible
http://piotrjagielski.com/blog/google-guava-vs-apache-commons-for-argument-validation/