最近在完成公司的一個上報徵信數據的項目,項目不大,因此開發人員就我一我的,可是工期挺緊,因此天天都寫代碼寫到起飛。項目到尾期後,有一些閒暇能夠 review 一下代碼。結果發現,我全部的參數校驗都是在 controller 層完成的,service 層沒有校驗。思索了一下,發現一個有趣的以前我沒有主要到的事情。前端
controller 層校驗後,能夠經過返回字符串的形式,提示前端異常信息;service 校驗後,須要返回 Exception 給上層。這會致使底層校驗產生大量的自定義 Exception,但底層校驗相比於頂層校驗能輻射系統的更多部分,要想保持系統的健壯性,底層校驗是必須的。那麼因爲底層校驗致使上層代碼涌現不少 try catch 怎麼辦?這些 try catch 還多是級聯的,一層一層拋出去。java
service 層(這裏舉了 service 層的例子,實際上能夠延伸到任何下層系統)可能拋出哪些異常?參數格式異常(好比要一段英文字符串,可是傳入了數字字符串),業務邏輯異常(好比,數據重複或者找不到)。第一次想到這裏的時候我腦殼裏想的全是 checked 異常。可是靈光一閃,我發現 java 不是還有 unchecked 異常嗎?編程
我們先思索一下,明確 checked 異常和 unchecked 異常的區別。checked 異常表示,這個異常的出現是正常的,容許的,因此你須要在編程階段考慮它。unchecked 異常表示這個異常是不正常的,它的出現表示你的代碼存在邏輯錯誤,因此你須要在編程階段保證它在運行時不發生。編程語言
如今咱們有了兩種異常定義的思路,一個是站在具體程序邏輯角度思考的(參數格式異常,業務邏輯異常),一個是站在編程語言角度思考的(checked 和 unchecked 異常)。學習
咱們來看看 java 本身是怎麼作的。設計
從 java 的一些庫的設計上來講,一般參數的格式都做爲一種協議,默認是你們都知道的,因此當格式錯誤的時候,程序拋出 unchecked 異常,你須要根據協議保證傳入參數的正確性。java 有一個異常叫 IllegalArgumentException,它的出現表示「參數的前提條件不成立」,這個「前提條件」就是參數的協議。因爲前提條件是經過文檔等提早說明的,因此這是一種可預期異常(當你調用一個方法的時候,你就知道哪些錯誤的參數會致使異常發生)。接口
java 有例子能夠來講明 checked 異常,如 IOException,程序的 IO 必然和硬件打交道,而硬件並不像程序同樣穩定,硬件可能掉電,可能因高溫損壞,這些都是不可預期的,IOException 就能夠用來表示與硬件交互過程當中發生的不可預期錯誤。因此 File 類中出現 IOException,Apache 的CloseableHttpClient 類中出現 IOException。開發
有了 java 的例子,咱們彷佛能夠更清晰的辨識 service 應該如何拋出異常了。簡單來講,可預期的錯誤是 unchecked 的,不可預期錯誤是 checked 的。好比用戶註冊的 service 層方法,用戶名,密碼的格式異常是 unchecked 的,用戶名已存在的異常是 checked 的。文檔
如此,大量的參數控制邏輯,能夠經過拋出一個 unchecked 的 IllegalArgumentException 來實現(向 java 學習),咱們也沒必要爲它們自定義異常類,上層也不會被它們困擾,上下層經過接口抽象來完成這種異常的處理。而另外一些不可預期的異常,咱們能夠經過拋出自定義異常類的方式來表達錯誤發生了。因爲剔除了參數校驗的異常,這部分須要上層 try catch 的異常的數量就顯得不是很可怕了,畢竟大多數業務邏輯可能根本不存在不可預期異常。字符串