サービス層はすべてのdao例外をキャッチし、それらをサービス例外としてラップする必要がありますか?


23

Dao、サービス、コントローラーの3つのレイヤーのSpring Webアプリがあります。コントローラーはdaoを直接呼び出すことはなく、サービス層を介して呼び出します。現時点では、ほとんどの場合、処理されないdao例外(ランタイム)があると、エンドユーザーにエラーメッセージを表示するJSPによってキャッチされます。サービス層はすべてのdao例外をキャッチし、それらをサービス例外としてラップする必要がありますか?

try {
   daoInstance.someDaoMethod();
} catch(DataAccessException dae) {
   throw new ServiceException("message", dae);
}

ServiceExceptionもランタイムであり、どちらも処理されないと仮定しましょう。ServiceExceptionの代わりにDataAccessExceptionをスローするだけの違いはありますか?私は、プレゼンテーション層がデータアクセス例外を認識すべきでないと考えました。しかし、単にそれらをラップするだけで回復不能な例外をキャッチするポイントは見当たりません。

回答:


18

重要な要因は、サービスクライアントが誰であるかだと思います。

サービスレイヤーが自分のプロジェクト内のレイヤー間のアーキテクチャ上の境界にすぎず、サービスクライアントが同じ信頼領域内にある場合は、物事を緩和し、未チェックの例外をコントローラーレイヤーまたはサービスクライアントにバブルします。

ただし、公開されているコードの場合、サードパーティまたは顧客によって消費されるサービス、主にセキュリティの問題、次に疎結合、クリーンな抽象化のために、未チェックの例外をサービス指向の例外でラップする方がクリーンだと思います。

データ層の例外は、決してWebアプリケーションのエンドユーザーに直接届かないようにしてください。スキーマ、クエリ、行番号情報、変数名または関数名などに関する内部情報が含まれている可能性があります。エンドユーザーの例外は安全な設定でサニタイズできます。

外部サービスクライアントは実装の詳細に関心がなく、チェックされていない例外はバグまたは環境の問題であるため、とにかく処理できません。セキュアなアプリケーションでは、データベースエラーは単純に伝播するほど安全OracleException - ORA-01234 - ...ではなく、挿入された3番目のテーブルである可能性があります。クライアントは、処理可能なチェック済み/予期される例外を処理し、他のすべてを潜在的なバグレポートとして扱うことができます。サービス契約は、アトミックで一貫性のあるトランザクション抽象化である必要があります。例外について何もできない場合、残っている唯一の有用なことは、バグレポートを提供することです。既に例外をログに記録する機能を持っているのに、なぜエンドユーザーに詳細を負担させるのですか?アプリが監視できるので、ユーザーがそれらを報告する前に、未チェックの例外を既に知っています。

例外を食べることは決して許されませんし、チェックされた例外のファンでもありませんが、製品全体の性質に適した計画を持っていることを好みます。


13

いいえ、WebアプリケーションでDAO例外をラップしないでください

ゼロのメリットのために、コードには多くのノイズがあります。DAO例外は、正当な理由により未チェックの例外です。アプリケーションコードは、DAO例外からの回復に役立つことはできません。実際の問題は次のとおりです。

...エンドユーザーにエラーメッセージを表示するJSPによってキャッチされます。

コードベース全体を圧縮するのではなく、この問題を1か所で修正します。

キャッチされない例外をユーザーに表示する方法を制御します。捕捉されなかった例外は、アプリケーションのバグまたは基盤となるシステムの障害が原因です。ユーザーにリクエストを処理できなかった理由に関する情報を提供する理由はありません。ユーザーができることは何もありません。すべきことは、フレンドリーなエラーページを提供することだけです。

注意:たとえば、単にラップして再スローするだけのキャッチブロックを作成するなど、多くの退屈なコードを書いていることに気付いた場合、ほとんどの場合、より良いソリューションがあります。


ご回答有難うございます。そして、はい、jspはカスタムメッセージを表示します:「おっと、何かがおかしい」。例外に関する情報は表示されません
オスカー14年

7

例外ラッピングを使用する主な理由は、ビジネスレイヤーのコードがシステムで起こりうるすべての例外について知る必要をなくすためです。これには主に2つの理由があります。

  • 一貫性:宣言された例外は、呼び出しスタックの最上部に向かって集計されます。例外をラップせず、代わりにスローするメソッドを宣言して渡すと、多くの異なる例外を宣言するトップレベルのメソッドになる可能性があります。各メソッドでこれらすべての例外を宣言すると、呼び出しスタックをバックアップするのが面倒になります。

  • カプセル化:最上位レベルのコンポーネントに、最下位レベルのコンポーネントについても、それらがスローする例外についても何も知らせたくない場合があります。たとえば、DAOインターフェースと実装の目的は、アプリケーションの他の部分からデータアクセスの詳細を抽象化することです。現在、DAOメソッドがSQLExceptionをスローする場合、DAOを使用するコードはそれらをキャッチする必要があります。データベースからではなくWebサービスからデータを読み取る実装に変更した場合はどうなりますか?次に、DAOメソッドはRemoteExceptionとSQLExceptionの両方をスローする必要があります。また、ファイルからデータを読み取るDAOがある場合は、IOExceptionもスローする必要があります。それは3つの異なる例外であり、それぞれが独自のDAO実装にバインドされています。

要するに、答えはイエスです!


3
JPA実装(Hibernateなど)は、未チェックの例外をスローします。それらを宣言したり捕らえたりする必要はありません。
ケビンクライン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.