アプリケーションのエラー処理について

今までエラー処理については

古典的なエラー処理方法
メソッドの戻り値でエラーコードを返し、呼び出し元ではif文でエラーコードに応じた処理をする
OOP的なエラー処理方法
エラー発生時にはメソッドが例外オブジェクトをthrowし、呼び出し元ではそれをcatchして処理する

と思っていたんだけれど、本当にOOP的なエラー処理方法はこれが正解なのかっていう疑問は常にあった。

例外は上手に使うとエラー処理をすっきりと簡潔に記述でき、プログラムの見通しも良くなるけれど、濫用しすぎると逆にプログラムの見通しを悪化させ、保守性も悪くなってしまう(単に例外をラップして再度投げるだけのcatch節とか、ログに書き込むだけとか)
さらに適切に例外をcatchしておかないと、5〜6階層上でSQLExceptionとか受け取ってなんのこっちゃ?となる。

あとストリームの終端に達したことを例外で検知するような仕様にしてしったりすると、戻り値を見てif文で処理をする場合と比べて、処理フローが見えづらくなる。


手元にある「Javaの鉄則―エキスパートのプログラミングテクニック」では例外処理についてこういう記述がある。以下同書から引用

例外は、予期せぬ(つまり、通常の動作ではない)状況に対して使用してください。
(中略)
つまり、すべての条件に例外を使うのではなく、それが意味を持つ場所(すなわち例外的な状況が存在する場所)で使うべきである、ということです。

ここでいう何を持って「予期できる」か「予期できない」とするのかは難しい問題なんだけれども、こういうことだろうと認識する。

予期される結果
通常の処理フローで起こりうる結果。メソッド内で対処することができる。
予期せぬ結果
通常の処理フローでは起こりえない結果。メソッドが処理を続行できない。

つまり

  • ストリームの終端に達する(EOF)
  • 照会クエリーの結果が0件
  • ユーザーのフォームへの入力値が不当

という場合は、設計時に発生することが十分予想できるので、メソッド内で対処を行い「戻り値」で処理するのが望ましく、

  • 特定のファイルが存在するか
  • xxxバイトのメモリーを確保できるか
  • 接続先のホスト(xxx.xxx.xxx.xxx)に接続できるか

といった実行時以外でチェックすることが不可能な事態は「例外」で呼び出し元に処理を委譲するのが正しいということ。

でいいのかなぁ。

ちなみに例外を使う大きなメリットの一つに「例外オブジェクトの中にエラーの発生状況を詳細に記述できる」というのもあるけれど。「予期できる」エラーでもこういった情報が必要であれば例外を使ったほうが良いのかな。わざわざ戻り値用のクラスを定義するってのもおかしな話だし。

一番重要なのは、プロジェクト内でエラー処理のポリシーを定めておくことだと思ったりw