たなかこういちの開発ノート

システム開発に携わる筆者が、あれこれアウトプットするブログ

エラーケースのパターン分類〔ライブラリ実装編〕

(※〔運用編〕からの続きです。)
 
エラーについての一連の記事では「処理」として「業務ロジック」を想定して議論を進めていました。では、その業務ロジックの実行環境・実行基盤たるフレームワークを実装するときや、日付演算ユーティリティ、XMLプロセッサーといった汎用のデータ処理ユーティリティーを実装するときは、どのような方針が適切でしょうか。
 
(1)外部資源のドライバーや業務ロジックの実行環境たるフレームワークの実装
 
フレームワークがアプリケーションへ公開しているメソッドAPI)の引数チェック
 
フレームワークがアプリケーションへ公開しているメソッドでは、引数チェックを行うでしょう。引数エラーがあった場合には、そのフレームワークメソッドを呼び出した業務ロジック側のmatter、業務ロジック側の内部エラーと考えます。それを表明するために、引数エラー発生時は一般のRuntimeException派生クラスをスローすべきです。
 
このことは、業務ロジックでは「呼び出された時に事前条件が満たされてなかった場合には、チェック例外をスローしてCondition YELLOWであることを表明する」、という方針に対して対照的です。
 
外部資源アクセス時のエラー
 
フレームワークやドライバーがDBMSなどの外部資源へアクセスし、そこでエラーが発生した場合は、フレームワークやドライバーにとって外的要因ですので、業務ロジックにとっても当然外的要因によるエラーとなります。よってオリジナルの例外を外的要因による旨を表すInfrastructureExceptionといった例外クラスにラップして、それを再スローします。
 
フレームワークの内部エラー
 
フレームワークの内部エラーは、その上で実行される業務ロジック対して外的要因による異常終了として提示するのが適切と考えます。つまり、Condition REDとして扱えるようなエラー応答を返すべきです。そのためには、業務ロジックから呼び出されるフレームワークの全てのメソッドでは、ロジックは全て“念のための”try〜catch(RuntimeException excp)で括り、万が一の非チェック例外の発生を捕捉するようにします。非チェック例外をcatchしたら、フレームワーク内部でのエラー発生である事を業務ロジックへ伝えるために、InfrastructureExceptionといった例外クラスにラップして、それを再スローします。業務ロジックを呼び出している側では、業務ロジックからスローされてきた例外をみて、それがInfrastructureExceptionであれば業務ロジックが依存しているフレームワーク内部で発生したエラー、一般のRuntimeException派生クラスであれば業務ロジックで発生したエラーであると判別できます。
 
(2)汎用的なデータ処理ユーティリティの実装
 
「データ処理ユーティリティ」とは、例えば、日付演算ユーティリティ、XMLプロセッサー、正規表現プロセッサー等のようなものを想定しています。「汎用」とは、アプリケーションの「業務ロジック」を実装するときに用いられるか、「(1)」で言及するところのドライバーやフレームワークを実装するときに用いられるか、ユーティリティ自身では決定できないことを表しています。このようなデータ処理ユーティリティを実装する場合、エラー発生時は全て一般のRuntimeExceptionをスローすべきと考えます。
 
データ処理ユーティリティがアプリケーションの業務ロジックから用いられる場合、ユーティリティから発生した非チェック例外はそのままスローされるので、アプリケーションの業務ロジックで発生した意図せぬ論理バグ、即ちCondition BLACKだと認識されることとなります。
 
「(1)」で言及するところのフレームワークのロジックから用いられる場合、ユーティリティから発生した非チェック例外はフレームワークのロジックの“念のための”try〜catch(RuntimeException excp)に捉えられInfrastructureExceptionといった固有の例外にラップされるので、業務ロジックにとって外的要因によるエラー、即ちCondition REDであると認識させるように扱えます。
 
◆以上