l

2014年2月11日 星期二

NullPointerException要怎麼處理?

Feb. 10 10:36~11:56

螢幕快照 2014-02-10 上午11.58.33

 

先打個廣告,兩天完整版的「第三梯次例外處理設計與重構實作班」確定開課,以下為課程簡介與報名網址,早鳥優惠到2/14日:

***

鄉民甲對於前幾天〈視力測驗:例外處理篇(1)〉的第2題有疑問,這一題的答案是C,但他認為NullPointerException也有可能交由例外處理來對付。

2.  以下那種狀況應該交由例外處理來對付,才不至於需要付出容錯設計的高額成本?

A. NullPointerException或NullReferenceException。

B. 陣列索引超出範圍。

C. 硬碟空間不足。

D. 以上皆是。

E. 以上皆非。

***

例子

鄉民甲告訴Teddy一個真實案例,如下圖所示,他有一個函數A呼叫一個外部程式(External Component),這個外部程式會產生Result.TXT檔案,然後函數A會讀取這個檔案,把檔案的內容顯示在畫面上。

螢幕快照 2014-02-10 上午10.52.23

 

Result.TXT有如下的格式:

2

……

XXXXX

YYYYY

2表示等一下繼續往下讀取兩筆資料(XXXXX和YYYYY),這兩筆資料就是要顯示在畫面上的資料。原本程式執行起來都很正常,一直到某一天程式發生了NullPointerException。經過一番調查之後,鄉民甲發現在某種狀況下,Result.TXT的內容會變成這樣子:

2

……

XXXXX

雖然顯示有2筆資料,但檔案裏面卻只有XXXXX,並沒有YYYYY。函數A先讀到2所以先配置了兩筆資料,但是最後只有一筆資料,所以第二筆資料的內容並沒有被初始化,因而產生NullPointerException,最後導致整個系統當機。

***

鄉民甲:我不希望程式因為NullPointerException而當機,這時候難道我不應該去捕捉NullPointerException以防止程式當機嗎?

Teddy:先請問一個問題,Result.TXT的內容出現了你們原本不預期的格式,請問這種現象是External Component的bug,還是屬於正常現象,只是你們當初沒有考慮到而已?

鄉民甲: 嗯…有什麼差別嗎?

Teddy:如果Result.TXT出現兩種不同的格式是因為External Component的bug所造成,而你們希望在函數A去「容忍」這個bug,因此去捕捉NullPointerException。這時候你們已經從例外處理提升到容錯設計的等級。

Teddy:如果Result.TXT出現兩種不同的格式是屬於「正常現象」,那問題就變成這是函數A的bug,因為函數A在「設計階段」沒有考慮到不同格式的問題。函數A的bug(design fault)應該是去修改函數A的程式碼,而不是用例外處理的方式來解決。

鄉民甲: 可是我也可以捕捉NullPointerException,把錯誤訊息寫在日誌檔中,然後讓程式繼續執行下去,這樣有什麼不可以的?

Teddy:如果你這麼做,你的系統就連「強健度等級1:錯誤回報」都沒達到。

鄉民甲:我不是有把錯誤訊息寫到日誌檔中了?

Teddy:錯誤訊息是有紀錄下來,但是使用者看不到啊。你剛剛提到的作法,當NullPointerException發生的時候,系統的狀態可能已經不正確了,但是你卻假裝什麼事都沒有,讓系統繼續執行,這樣只會讓後續的除錯變得更加困難。你可以把NullPointerException往上傳遞,在最外層的程式中捕捉這個例外,然後顯示錯誤訊息給使用者看,這樣比把錯誤訊息偷偷記在日誌檔中然後假裝沒有錯誤發生讓程式繼續執行要來的好。

***

忽略例外處理,類似82億次駭客攻擊事件的烏龍,絕對還會出現。

***

友藏內心獨白:辦理結婚登記等六小時又是怎麼回事?

沒有留言:

張貼留言