山下寛人オフィシャルブログ

オイシックス株式会社 執行役員 システム本部長 山下寛人の公式ブログです。

例外処理の設計

例外処理をちゃんと設計できる人はなかなかいないと思います。

なぜなら答えがないから。

しかし長年運用してきた経験からいくらかノウハウはあります。


よくある悪い例・例外を握りつぶしてしまう

基本ですがよく飲み込んで消してしまう人がいます。

try {
:
} catch (Exception e) {
}

どうしていいかわからなかったらたいがいはラップしてthrowすれば

間違いないです。

try {
:
} catch (Exception e) {
throw new IllegalArgumentException(e);
}

無視して処理を続けてもよいものなら飲み込んでもかまいません。
ログにスタックトレースを出したうえで処理を継続していい場合もあります。

よくある悪い例・むやみにthrowsをつける

検査例外があるとcatchするのが面倒なのかすぐthrowsをつけて

コンパイルを通してしまう人がいます。

最悪の場合 throws Exception を宣言していることも。

throwsをつけるとメソッドの呼び出し側ではcatchしなければならなく

なります。

しかしcatchしてからどうしていいかわからない場合、困って

しまいます。

こういうふうに意味不明なthrowsが多いことが例外の握りつぶしに

つながっているとも思えます。


ではどうしたらいいか。

基本的に非検査例外を使うようにします。

全部でもいいかもしれません。

どうしても呼び出し側にcatchさせたい場合のみ検査例外を使います。


throwする例外は呼び出し元に内容がわかる例外にします。

ExceptionやRuntimeExceptionでは何がおこったのかわかりませんね。

自作のExceptionを使うなり、適切なExceptionでラップしてthrowします。


例外処理についてはいろいろ議論があって答えが出ていません。

Javaの理論と実践: 例外をめぐる議論

これを見るとやはり非検査例外を使うほうが主流のようです。

C#ではJavaの反省から全て非検査例外になっています。


他にも処理の成功失敗をメソッドの返り値で返すように作る人がいますが

これは例外をthrowしてほしいです。なぜなら下記のようになっている場合。

catch (Exception e) {
return false;
}

何か例外が発生した場合、原因がわかりにくくなってしまいます。

例外のスタックトレースは障害対応に非常に有用です。


try-catchブロックの範囲の広さをどうするかは悩ましいところです。

狭すぎるとtry-catchだらけになりコードが読みにくくなります。

広すぎると例外がどこで出る可能性があるのかわかりにくくなります。

このへんは狭すぎず広すぎずといった形でしょうか。

1メソッドが25行以内など短く作られていれば広くなりすぎることは

ないかもしれません。