5

同社のシステムの例外処理の 1 つを調べたところ、いくつか興味深いことがわかりました。

ほとんどのコード ブロック (すべてではないにしても) は try/catch ブロック内にあり、catch ブロック内で新しい BaseApplicationException がスローされています。これはエンタープライズ ライブラリから来ているようです。これを行うメリットが見当たらないので、ここで少し困っています。(例外が発生するたびに別の例外をスローする) しばらくシステムを使用している開発者の 1 人は、そのクラスが例外の発行 (メールなどの送信) を担当しているためだと言いましたが、彼はそれについてあまり確信が持てませんでした。しばらくコードを調べてみたところ、環境に関する情報を収集し、それを公開するだけであると確信しています。

私の質問は次のとおりです。もしそうなら、なぜですか?メリットは何ですか?

私の個人的な意見では、HttpModule を使用し、Application イベントの Error イベントにサインアップし、モジュール内で必要なことを行う方がはるかに簡単です。この道を行くとしたら、何かを逃すでしょうか?欠点はありますか?

あなたの意見は大歓迎です。

4

6 に答える 6

10

決して1 catch (Exception ex) . 期間.キャッチする可能性のあるさまざまな種類のエラーをすべて処理する方法はありません。

例外派生型を処理できない場合、または追加情報 (後続の例外ハンドラーで使用される) を提供できない場合は、決して例外派生型をキャッチしないでください。エラー メッセージを表示することは、エラーを処理することと同じではありません

私の頭の上から、これにはいくつかの理由があります。

  • キャッチと再スローにはコストがかかります
  • スタックトレースを失うことになります
  • コードの信号対雑音比が低くなります

特定の例外を処理する方法 (およびアプリケーションをエラー前の状態にリセットする方法) を知っている場合は、それをキャッチします。(そのため、例外 処理と呼ばれます。)

キャッチされない例外を処理するには、適切なイベントをリッスンします。System.AppDomain.CurrentDomain.UnhandledExceptionWinForms を実行する場合は、をリッスンする必要があります。実行する場合は、Web アプリThreadingSystem.Windows.Forms.Application.ThreadException.場合、同様のメカニズムがあります ( System.Web.HttpApplication.Error)。

フレームワークの例外をアプリケーション (非) 固有の例外 (つまりthrow new MyBaseException(ex);) にラップすることについては、まったく無意味で、悪臭がします。4


編集

@Chris がコメントで指摘したように、特にエンジニアリングに関しては、決して非常に厳しい言葉ではありません。この回答を最初に書いたとき、私は原則に忠実であることを認めます。

2,3 1を参照してください。

4新しいことを提案しなくても、私はこれを支持します。Exception exさまざまな方法で失敗する可能性があることがわかっているメソッドの一部としてキャッチした場合、現在のメソッドはそれを署名に反映する必要があると思います。ご存知のように、例外はメソッド シグネチャの一部ではありません。

于 2008-09-25T12:35:48.357 に答える
2

私が質問を正しく読んでいる場合、例外をインターセプトするtry / catchを実装して(あなたは言及しません-それはすべての例外をキャッチするのですか、それとも特定の例外だけをキャッチするのですか?)、別の例外をスローすることは一般的に悪いことです。

短所:

少なくとも、スタックトレース情報が失われます(表示されるスタックは、新しい例外がスローされたメソッドにのみ拡張されます)。ここでは、適切なデバッグ情報が失われる可能性があります。

例外をキャッチしている場合は、OutOfMemoryやStackOverflowなどの重要な例外を、それほど重要ではない例外でマスクするリスクがあります。そのため、プロセスは実行されたままになります。

考えられる利点:

非常に特殊なケースでは、デバッグ値があまりない例外(データベースから返される例外など)を取得し、処理しているオブジェクトのIDなどのコンテキストを追加する例外でラップすることができます。

ただし、ほとんどの場合、これは悪臭であるため、注意して使用する必要があります。

一般に、その場所で実行できる現実的なことがある場合にのみ例外をキャッチする必要があります。つまり、回復、ロールバック、プランBに進むなどです。それについて何もできない場合は、チェーンを通過させてください。 。その場所で元の例外を補強し、デバッグに役立つ特定の有用なデータが利用できる場合にのみ、新しい例外をキャッチしてスローする必要があります。

于 2008-09-25T12:07:26.833 に答える
1

私は、try/catch ブロックを使用し、例外を再スローしないという考え方の学校の出身です。エラーが発生する可能性のあるコードを実行している場合は、それを処理してログに記録し、何かを返す必要があります。例外の再スローは、アプリケーション ライフ サイクルの後半で再度ログを記録する目的にのみ役立ちます。

HttpModule を使用して例外を処理する方法に関する興味深い投稿を次に示します。 net-application.aspxおよびhttp://blogs.msdn.com/rahulso/archive/2008/07/18/asp-net-how-to-write-error-messages-into-a-text-file-using- a-simple-httpmodule.aspx

于 2008-09-25T11:54:55.350 に答える
1

エルマーをチェックしてください。それはあなたが話していることをします。結構。

ライブラリを作成するときは、呼び出し元が処理する例外の数を常に減らすようにしています。たとえば、SQL データベースに接続するリポジトリ コンポーネントについて考えてみましょう。SQL クライアントの例外から無効なキャストの例外まで、理論的にスローできる例外はたくさんあります。これらの多くは明確に文書化されており、コンパイル時に説明できます。そのため、できる限り多くの例外をキャッチし、単一の例外タイプ (RepositoryException など) に配置して、その例外をコール スタックにロールアップさせます。

元の例外が保持されるため、元の例外を診断できます。しかし、私の呼び出し元は、大量のさまざまな catch ブロックでコードを散らかすのではなく、1 つの例外の種類を処理することだけを心配する必要があります。

もちろん、これにはいくつかの問題があります。最も注目すべきは、呼び出し元がこれらの例外の一部を処理できる場合、RepositoryException 内をルートし、それを処理するために内部例外の型をオンにする必要があることです。単一の例外タイプに対して単一の catch ブロックを使用するよりもクリーンではありません。しかし、それはあまり問題ではないと思います。

于 2008-09-25T11:58:26.590 に答える
0

スローされた例外のように聞こえますが、例外として実装されるべきではありませんでした。

とにかく、このBaseApplicationExceptionは汎用の例外であるため、よりコンテキスト固有の例外をスローすることをお勧めします。したがって、データベースからエンティティを取得しようとしている場合は、EntityNotFoundExceptionが必要になる場合があります。このように、デバッグしているときに、実際の問題を見つけるために内部例外やスタックトレースを検索する必要はありません。このBAseApplicationExceptionが例外に関する情報を収集している場合(内部例外の追跡など)、これは問題にはなりません。

HttpModuleを使用するのは、コード内で実際に例外が発生している場所に近づくことができなかった場合のみです。BaseApplicationexceptionのエラー情報に依存する巨大なswitchステートメントであるHttModuleOnErrorイベントは実際には必要ありません。

結論として、問題の根本をすぐに伝えるより具体的な例外を与えることができる場合は、さまざまな例外をスローすることは価値があります。

于 2008-09-25T12:00:59.937 に答える
0

私の経験から、例外をキャッチし、サーバー(?)オブジェクトにエラーを追加します。これにより、.NETは必要な処理を実行し、例外を表示できるようになります。

于 2008-09-25T12:02:34.910 に答える