5

データ アクセス層の奥深くまたはさらに上位 (たとえば、ADO.net 操作内など) で発生するエラーは、エンド ユーザーにとってほとんど意味がありません。これらのエラーを UI にバブルアップして表示するだけでは、通常、エンド ユーザーのフラストレーション以外には何も達成されません。

私は最近、このようなエラーを報告するための基本的な手法を採用しました。これにより、エラーをキャッチし、少なくともエンドユーザーが何が失敗したかを理解できるように、少なくともユーザーフレンドリーなテキストを追加します。

これを行うために、各特定の関数 (たとえば、データ アクセス レイヤーのフェッチ関数など) 内で例外をキャッチし、失敗した関数とおそらく原因についてユーザー フレンドリーなテキストで新しいエラーを発生させますが、元の関数を埋め込みます。その新しい例外の「内部例外」としての新しい例外の例外。

これは、必要に応じて各レイヤーで発生し、下位レベル関数の各コンシューマーが独自のコンテキストをエラー メッセージに追加することで、UI に到達するエラー メッセージがますますユーザー フレンドリーになります。

エラーが UI に到達すると (必要に応じて)、ネストされた例外を繰り返し処理して、最初にどの操作が失敗したかをユーザーに通知するだけでなく、実際に何がうまくいかなかったのかについての技術的な情報も提供するエラー メッセージを表示できます。

例えば

「リクエストされた顧客名のリストを表示できませんでした。」

「データベースにエラーが発生したため、要求した顧客のリストを取得できませんでした。」

「顧客リストの取得中にデータベースへの接続中にエラーが発生しました」

「ユーザー xx のログインに失敗しました」

私の質問はこれです: これはひどく非効率的ですか (ネストされたすべての例外)? 私はそれがベストプラクティスではないと思うので、同じことを達成するために何をすべきですか?

4

6 に答える 6

9

それはほんの少し恐ろしいです。

エンドユーザーにエラーを表示している場合、ユーザーはそれについて行動できるはずです。「リクエストされた顧客名のリストは表示できませんでした。」その場合、ユーザーは「だから何?」と思うだけです。これらのすべてのケースで、「何か悪いことが起こった」というメッセージを表示するだけです。これらの例外をキャッチする必要さえありません。何か問題が発生した場合は、何らかのグローバル メソッド (application_error など) に処理させて、一般的なメッセージを表示させます。あなたまたはあなたのユーザーがエラーに対して何かできる場合は、それをキャッチして実行するか、ユーザーに通知します。

ただし、処理しないすべてのエラーをログに記録する必要があります。

ちなみに、発生したエラーに関する情報を表示すると、セキュリティ上の脆弱性につながる可能性があります。攻撃者がシステムについて知らないほど、システムをハッキングする方法を見つける可能性は低くなります ("SQL ステートメントの構文エラー: Select * From Users Where username='a'; drp database;--'.. ." 予想: 'drp' の代わりに 'drop'. 彼らはもうこのようなサイトを作りません)。

于 2008-09-20T23:50:06.030 に答える
8

新しい例外をスローすることは技術的にコストがかかりますが、「コストがかかる」というのは相対的なものであるため、大きな議論はしません。1分間に100個のそのような例外をスローする場合、コストは表示されない可能性があります。このような例外を1秒間に1000回スローすると、パフォーマンスが低下する可能性があります(したがって、ここで説明する価値はありません。パフォーマンスが重要です)。

なぜこのアプローチが使われているのか、私は尋ねなければならないと思います。例外がスローされる可能性のあるすべてのレベルで意味のある例外情報を追加できるというのは本当に本当ですか。もしそうなら、その情報は次のようになるということも本当ですか。

  • 実際にユーザーと共有したいことはありますか?
  • ユーザーが解釈、理解、使用できるものはありますか?
  • 低レベルのコンポーネントの後での再利用を妨げないように書かれていますが、それらが書かれたときにその有用性がわからない可能性がありますか?

あなたの例では、データベースでの認証に問題があったことをユーザーに通知することから人工スタックが開始されるため、ユーザーとの情報の共有について質問します。潜在的なハッカーにとって、それは操作が何をしていたかについて何かを明らかにする良い情報です。

カスタム例外スタック全体を返すことに関しては、ほとんどの(正直な)ユーザーにとって役立つものではないと思います。たとえば、顧客名のリストを取得するのに問題がある場合、データベースでの認証に問題があったことを(ユーザーとして)知るのに役立ちますか?統合認証を使用していて、各ユーザーがアカウントを持っていて、システム管理者に連絡して、アカウントに特権がない理由を確認する機能がない限り、おそらくそうではありません。

まず、スローされたFramework例外と、ユーザーに提供したい例外メッセージとの間に実際に意味上の違いがあるかどうかを判断することから始めます。存在する場合は、先に進み、最下位レベルでカスタム例外を使用します(この例では「ログインに失敗しました」)。その後の手順では、例外が実際に表示されるまで、カスタム例外は実際には必要ありません。関心のある例外はすでに生成されています(ログインに失敗しました)。コールスタックのすべてのレベルでそのメッセージをラップし続けることは、ユーザーにコールスタックを公開する以外の本当の目的にはなりません。これらの「中間」ステップでは、try / catchブロックが適切に配置されていると仮定すると、単純な「ログアンドスロー」戦略が適切に機能します。

ただし、実際には、この戦略には別の潜在的な欠陥があります。それは、実装されたカスタム例外標準を維持する責任を開発者に強いることです。低レベルの型を作成する場合、呼び出し階層のすべての順列を知ることはできないため(「クライアント」はまだ作成されていない可能性があります)、すべての開発者(または1人の開発者)がラップしてカスタマイズすることを覚えている可能性は低いようです。すべてのコードブロックのエラー状態。

私は通常、下から上に向かって作業するのではなく、プロセスのできるだけ遅い段階(つまり、呼び出しスタックの「最上位」にできるだけ近い場所)でスローされた例外が表示されることを心配しています。通常、アプリケーションの低レベルでスローされた例外のメッセージを置き換えようとはしません。特に、これらの低レベルのメンバーの使用は、呼び出しが深くなるほど抽象化される傾向があるためです。私は、ビジネス層以下で例外をキャッチしてログに記録し、プレゼンテーション層でそれらをわかりやすく表示する傾向があります。

例外処理のベストプラクティスに関するいくつかの適切な記事を次に示します。

http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx

http://aspalliance.com/1119

うわあ、これは言葉になりました...事前にお詫びします。

于 2008-09-21T00:36:29.210 に答える
3

はい、例外は高価なので、キャッチして再スローするか、より有用な例外をスローすることにコストがかかります。

でもちょっと待って!使用しているフレームワーク コードまたはライブラリが例外をスローする場合、問題はすでに解決しています。例外に続いてエラーメッセージが伝播される速度について、機能以外の要件はありますか? 疑わしい。それは本当に大したことですか?予期せぬ「例外的な」ことが起こりました。重要なことは、賢明で役立つ情報をユーザーに提示することです。

あなたがしていることは正しい軌道に乗っていると思います。

于 2008-09-20T23:49:09.700 に答える
2

私が働いているところでは、例外をキャッチする理由はいくつかあります。私たちはそれをするときだけそれをします...

  1. 私たちはそれについて何かをすることができます-例えば、これは時々起こる可能性があることを知っており、それが起こったときにコードで修正することができます(非常にまれです)。

  2. それがどこで発生するかを知りたいのです(その後、例外を再スローします)。

  3. わかりやすいメッセージを追加したいのですが、その場合、元の例外をアプリケーションの例外から派生した新しい例外でラップし、それにわかりやすいメッセージを追加して、その時点から変更せずにバブルさせます。

あなたの例では、おそらく「ログオンエラーが発生しました」と表示するだけです。anbdは、実際のエラーをログに記録し、ユーザーが必要に応じて例外にドリルダウンする理由を提供する間、そのままにしておきます。(おそらくエラーフォームのボタン)。

  1. 例外を完全に抑制し続けたいと思います。言うまでもなく、これは予想される例外タイプに対してのみ、例外を生成する条件を検出する他の方法がない場合にのみ行います。
于 2008-09-21T00:24:30.597 に答える
2

もちろん、それは恐ろしく非効率的です。しかし、エンドユーザーに表示するのに十分重要な例外が発生した時点では、それを気にする必要はありません。

于 2008-09-20T23:45:07.213 に答える
1

通常、例外を処理する場合、パフォーマンスと効率はほとんど心配しません。ユーザーが問題から回復するのを助けるために何かをすることについてもっと心配する必要があります。特定のレコードをデータベースに書き込む際に問題が発生した場合は、変更をロールバックするか、少なくとも行情報をダンプして、ユーザーが行情報を失わないようにします。

于 2008-09-20T23:47:37.190 に答える