iteye精華帖之異常大討論
原帖鏈接http://www.iteye.com/topic/2038
Robbin的觀點
觀點1:Exception實際上代表了一個UseCase中的異常流的處理。
絕大多數的Java程序員根本就沒有領悟“Exception”的真正用處。他們就是把Exception當做異常來理解,沒有明白Exception實際上代表了一個UseCase中的異常流的處理。
在使用UseCase來描述一個場景的時候,有一個主事件流和n個異常流。異常流可能發生在主事件流的過程,而try語句里面實現的是主事件流,而catch里面實現的是異常流,在這里Exception不代表程序出現了異常或者錯誤,Exception只是面向對象化的業務邏輯控制方法。如果沒有明白這一點,那么我認為並沒有真正明白應該怎么使用Java來正確的編程。
而我自己寫的程序,會自定義大量的Exception類,所有這些Exception類都不意味着程序出現了異常或者錯誤,只是代表非主事件流的發生的,用來進行那些分支流程的流程控制的。例如你往權限系統中增加一個用戶,應該定義1個異常類,UserExistedException,拋出這個異常不代表你插入動作失敗,只說明你碰到一個分支流程,留待后面的catch中來處理這個分支流程。傳統的程序員會寫一個if else來處理,而一個合格的OOP程序員應該有意識的使用try catch 方式來區分主事件流和n個分支流程的處理,通過try catch,而不是if else來從代碼上把不同的事件流隔離開來進行分別的代碼撰寫。
觀點2:用boolean做返回值判斷方法是否執行成功是錯誤的
另外糾正一個錯誤的觀點:很多人喜歡定義方法的返回類型為boolean型的,當方法正確執行,沒有出錯的時候返回true,而方法出現出現了問題,返回false。這在Java編程當中是大錯而特錯的!
方法的返回值只意味着當你的方法調用要返回業務邏輯的處理結果的。如果業務邏輯不帶處理結果,那么就是void的,不要使用返回值boolean來代表方法是否正確執行。
例如 用戶登陸方法
(注:Robbins認為錯誤的寫法:)
- boolean login(String username, String password);;
很多人喜歡用boolean返回,如果是true,就是login了,如果false就是沒有登陸上。其實是錯誤的。還有的人定義返回值為int型的,例如如果正確返回就是0,如果用戶找不到就是-1,如果密碼不對,就是-2
- int login(String username, String password);;
然后在主程序里面寫一個if else來判斷不同的流程。
- int logon = UserManager.login(xx,xx);;
- if (logon ==0); {
- ...
- } else if (logon == 1); {
- ...
- } else if (logon ==2); {
- ..}
這是面向過程的編程邏輯,不是面向對象的編程邏輯。
(注:Robbins認為正確的寫法:)
- User login(String username, String password); throws UserNotFoundException, PasswordNotMatchException;
主程序這樣來寫:
- try {
- UserManager.login(xx,xx);;
- ....
- 用戶登陸以后的主事件流代碼
- } catch (UserNotFoundException e); {
- ...
- 用戶名稱沒有的事件處理,例如產生一個提示用戶注冊的頁面
- } catch (PasswordNotMatchException e); {
- ....
- 密碼不對的事件處理,例如forward到重新登陸的頁面
- }
觀點3:用分層與返回值的角度看異常
什么叫做程序拋出的異常,什么叫做系統拋出的異常,你能明確界定嗎?FileNotFoundException你說算是系統異常呢?還是程序異常?站在某些程序員的角度,他會覺得是系統異常,不過像我喜歡看JDK源代碼的人來說,我對Sun的程序什么情況下拋出FileNotFoundException很清楚,這些代碼對我來說,和我自己寫的代碼能有什么不同嗎?對我來說,FileNotFoundException就是程序異常。既然JDK可以拋出異常,憑什么我就不能拋出異常?
站在底層程序員的角度來看,根本沒有什么系統異常可言,否則的話,還不如不要定義任何異常得了,干脆就是函數調用返回值,你說為什么Sun不定義0,1,2這樣的返回值,而是拋出異常呢?Java程序無非就是一堆class,JDK的class可以拋異常,我寫的class為什么不能拋出?
異常不異常的界定取決於你所關注的軟件層面,例如你是應用軟件開發人員,你關心的是業務流程,那么你就應該捕獲底層異常,就應該定義業務層異常,向上拋出業務層異常。如果是底層程序員,你就應該定義和拋出底層異常。要不要拋出異常和拋出什么異常取決你站在什么軟件層面了,離開這個前提,空談異常不異常是沒有意義的。
觀點4:使用異常可以提高程序可讀性
舉個簡單的例子 一個權限判斷的方法
boolean checkUserPermission(User user, int mId) throws NoExistUserException, NoExistModuleException {
}
我並不能保證有誰會使用這個權限判斷的方法,但按照面向對象的理論,程序中最好只有一個實現相同功能的方法,所以我定義了不存在用戶和不存在模塊的異常,這樣不管是程序組中誰使用這個方法,就可以清楚的知道這個方法實現的功能,也可以知道出錯了是因為什么原因出錯也就可以采取相應的方法去處理 。