前沿
異常設計準則,參考微軟msdn,結合自己的理解和過去的開發中對異常錯誤的處理,總結下軟體開發架構,如何更好地設計一套異常錯誤準則。
介紹準則
execution failure概念
The meaning of execution failure: execution failure occurs whenever a member cannot do what it was designed to do (what the member name implies). For example, if the OpenFile method cannot return an opened file handle to the caller, it would be considered an execution failure.
翻譯:
操作失敗的意思:無論什麼時候一個成員模組不能完成它預期的任務時,就稱為發生了一次操作失敗。例如OpenFile方法不能給caller返回一個開啟檔案的控制代碼,這就是一次操作失敗。
架構中處理異常
In the Framework, exceptions are used for all error conditions, including execution errors.
翻譯:
在架構中,異常被用來處理所有的錯誤條件,包括執行錯誤。
總結準則
哪些方法在設計異常時應該被禁止,哪些應該要without hesitation to do,哪些需要考慮,都列在下方的表格中。
編號 |
方法 |
做法 |
1 |
返回錯誤碼 |
禁止 |
2 |
執行錯誤,要拋出異常;如OpenFile()未返迴文件控制代碼 |
建議 |
3 |
假如代碼再繼續執行就變得不安全時,考慮是調用System.Environment.FailFast終止進程還是拋異常。 |
考慮 |
4 |
如果有可能的話,在正常的控制流程處,拋異常,見下面的分析 |
禁止 |
5 |
拋異常對效能的影響。 |
考慮 |
6 |
協定中納入異常處理部分 |
建議 |
7 |
將異常作為傳回值返回 |
禁止 |
8 |
使用異常產生器方法,為避免代碼膨脹, 用helper方法建立異常和屬性. |
考慮 |
9 |
異常篩選器中拋出異常. |
禁止 |
10 |
從finally 塊中顯示地拋出異常 |
禁止 |
對第4條做說明:
In daily coding, consider the Tester-Doer pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions. The Tester-Doer pattern pides a call that might throw exceptions into two parts: a Tester and a Doer. The Tester performs a test for the state that can cause the Doer to throw an exception. The test is inserted just before the code that throws the exception, thereby guarding against the exception. 來自http://blog.csdn.net/troubleshooter/article/details/18401491
參考的例子代碼:
Tester和Doer各司其職,完美的減少了異常拋出,提升效能。
Doer:上面的狀態監測是好的,才能DoProcess()處理;如果是false,並且如果DoProcess()中包括DoCheck()邏輯,則會拋出異常,但是這樣分隔開後,DoProcess()將不會拋出異常!
if(DoCheck()==true)//這是Tester:狀態監測 DoProcess();
軟體開發常見異常及處理方式(自己總結)
1 UI層暴露出的操作介面,建議包裹try{}catch{}塊,catch中將拋出的異常寫入到磁碟中。
2 UI層中用到計時器時,計數器的回呼函數出現異常後,要stop掉計時器,防止錯誤記錄檔一直寫進檔案中。
3 底層建議不包裹try{}catch{}塊,建議用throw直接拋出異常,因為UI層上包裹了try{}和catch{}塊,所以沒必要寫在這些層。
4 throw會直接中斷以後操作,跳轉到所屬堆棧外層包裹try{}和catch{},即UI層,利用這個性質,一般建議函數不要返回錯誤碼。
5 處理大量匯入的資料時,局部出現異常。Excel匯入人員,裝置,計劃,物料,工藝等,如果某一行資料違規了,這時候不建議拋出異常,因為一旦拋出異常,意味著後面行的資料匯入不進來,並且已經匯入進去的成為髒資料。
一般有兩種做法:某行出現違規資料,記錄到記錄檔中,日後根據這個檔案查到那條資料未匯入,然後單獨處理這一條即可;在匯入前,直接檢查所有行的資料是否合法,檢查無誤後,再一一匯入,否則直接彈出提示,任何資料都寫不到資料庫中。一般建議後者做法。這種做法稱為:Tester-Doer異常模式,也是微軟建議的做法。
6 處理看板展示資料,局部出現異常。這個處理模式跟5是有區別的,一般此時出現異常,往往採取5的前者做法:展示出正確的資料,違規的資料寫入到日誌中,留待查看;但是也有可能,如果展示的介面,主要的資料不存在,則直接拋出異常,寫入日誌,通過日誌解決。因此要根據資料的異常嚴重程度去處理。
7 根據開發文檔、日誌,分析,盡量做到能夠找到某個功能未實現的原因。首先要保留好開發文檔,查看使用者現在的要求是不是和開發文檔中的一致。如果一致,此時日誌的作用就顯示出來了,例如,匯總一周內所有工序的完工餅狀圖,如果一條工序資料都沒有,那麼餅狀圖可能就沒有,在開發過程中,如果檢查了是不是存在工序,如果沒有找到一條工序,可能會拋出異常,然後寫入日誌地話,原因就會找到。因此這類問題,也要寫入日誌,儘管它不是錯誤,但可以歸為異常。
8 函數返回一個對象,其方法和屬性被後續邏輯引用。這是不可避免的!並且大部分功能的實現都依賴於此。返回的這個對象因為要被後續引用,所以建議做null比較,如果為null,是傳遞給UI層,彈出訊息提示,還是直接拋出異常,UI層處理後寫入日誌,視情況而定。