l

2013年11月27日 星期三

找不到資料要傳回Null還是丟出Exception?

Nov. 25 13:12~13:58

image

 

上禮拜Teddy到某校資訊系演講,講題一樣是「例外處理設計與重構」。在演講中Teddy舉了幾個語言例外處理的壞味道,例如return code與ignored checked exception等。Teddy建議在還不知道例外要如何處理的時候,不要去捕捉、隱藏、忽略例外,此時應該採用fail-fast策略,丟出例外並且讓程式終止。

演講結束之後有一位同學問了Teddy一個問題…

同學:你剛剛建議我們不要用return code來代表例外,假設我要設計一個依據學號到資料庫中查詢學生資料的函數。如果找不到符合條件的學生資料,是不是應該要丟出例外?

Teddy:不一定,這要看你的需求與設計。假設你的function長成這樣public List<Student> queryStudents(String ID),傳回一個大小為0的List就可以代表找不到學生資料的情況。

同學:那如果我的function只會回傳一個學生物件呢?

Teddy:假設你的function長成這樣public Student queryStudent(String ID),只傳回一個物件,那麼你就要問自己:「依據ID來尋找學生資料,但最後找不到任何一筆符合條件的資料」,這種情況,算是正常狀況還是異常狀況?

同學:…

Teddy:如果你問我的看法,我會覺得這是正常狀況。在日常生活中,依據某些條件去找資料,最後找不到任何符合條件的資料,算是一種很常見的狀況,所以我不會針對這種情況丟出例外。所以你可以傳回null用來代表找不到任何資料,如果不喜歡null,也可以套用Null Object設計模式,傳回一個Null Object來表示找不到符合條件的資料。

***

同學所問的問題,可以用下圖來解釋。Exception在程式語言中用來代表error與failure,分別表示「目前可能處在不正確的狀態」與「被呼叫的服務或函數辦事不力」。「找不到資料」並非狀態錯誤,也不是尋找資料的函數辦事不力。事實上,尋找資料的函數正確執行完畢,只不過沒有找到符合查詢條件的資料罷了。這種狀況是在規格中所允許的狀況,和例外處理無關,只要在設計介面的時候規定好傳回某種特殊值(null 或Null Object)代表找不到資料這樣就可以了。

螢幕快照 2013-11-25 下午1.42.56

***

友藏內心獨白:有人問問題,講者心中應該要放鞭炮了。

2 則留言:

  1. 這算是我經驗當中遇到最多人問的問題,有些人就想到返回什麼錯誤值,有些人又說拋 Exception 效能低,而有些更分不清楚到底檢查和消毒 (sanity)的責任應放在 caller 還是 callee 上面。 就是分不清什麼時候該拋 Exception,什麼時候它是正常流程該處理的事情。

    這題目值得用多些例子深入討論。

    回覆刪除
  2. If you are tempted to return null from a method, consider throwing an exception or returning a SPECIAL CASE object instead. -Robert C. Martin

    看來2位大師唯一有共識的是"returning a SPECIAL CASE object instead".

    回覆刪除