18

最近、Jeffrey Richter の .NET に関するトレーニング コースに参加しました。彼は、「死ぬことは素晴らしい」というコーディングの戦略の 1 つに言及しています。つまり、プログラムやイベントループのルートにも「catch (Exception ex)」を書かないでください。処理されない例外がスローされた場合は、プロセスを終了させます。

これが正しいかどうかはわかりません。個人的にはtry {...} catch(Exception ex) {log and try to recover}、最上位の実行で " " をラップすることを好みます。実際、asXx から何らかの例外がスローされても、ASP.NET は停止しません。例外が原因で停止した場合は、1 つの特効薬のリクエストでサービス全体を停止できます。

どう思いますか?

4

16 に答える 16

38

実行しているアプリの種類と、「死ぬ」ことの結果がどうなるかによると思います。多くのクライアント アプリにとって、死ぬことは素晴らしいことです。サーバーの場合、多くの場合、それほど多くはありません (飲み込んでログを記録するのが適切です)。万能のソリューションはありません。

于 2009-02-23T04:40:18.533 に答える
22

攻撃的プログラミングとも呼ばれます。

「攻撃的なプログラミング: 早期にクラッシュし、頻繁にクラッシュする」をチェックしてください。

これは、防御的プログラミングの規範とは非常に異なるイデオロギーです:

[防御的プログラミング] は、ソフトウェアの予測不可能な使用にもかかわらず、ソフトウェアの継続的な機能を保証することを目的としています。

私は個人的に「早くクラッシュし、頻繁にクラッシュする」という哲学が好きです。

私はあまりにも多くを見てきました:

try  
{  
    // ... Huge block of code goes here  
}  
catch(Exception ex)  
{  
   // Do nothing...  
}  

これは、激しくクラッシュするよりもはるかに悪いことです。例外が適切に処理されれば、多少の防御的なプログラミングは問題ありません。

于 2009-02-23T04:44:22.920 に答える
8

それはすべて、例外をどのように扱うかによって異なります。本当に例外的なことが起こったときにのみ例外をスローする場合 (データベース クエリが結果を返さない場合や形式が正しくない場合ではない場合) は、例外をキャッチする必要はありません。プログラムは回復できないはずなので、回復できるものはすべて例外ではなく、エラーです。

于 2009-02-23T04:38:11.050 に答える
8

Karl Seguinは、例外処理について次のように述べています。

  1. 実際に対処できる例外のみを処理する
  2. 大多数の例外については何もできません

主題へのよい導入。

于 2009-02-25T12:10:54.127 に答える
8

グルスピークみたい

これは、グルによって説教された一般的なガイドラインの 1 つに思えますが、それ自体は悪いアドバイスではありません。ただし、このガイドラインは、それが属していない場所にも簡単に適用できます。上記で使用したことを覚えておくべき重要なフレーズは「コーディングの 1 つの戦略」だったと思います。この戦略は特定のドメインでは非常に有用ですが、他のドメインでは非常に有害な場合があるからです。

死ぬこと素晴らしいことです。状態が互いに依存する密結合コンポーネントが多数ある場合、例外は簡単に壊滅的なイベントになる可能性があります。ただし、目標の 1 つは、1 つの障害でシステム全体がダウンする必要がないようにコーディングすることです (目標に注意してください)。

次のアプリケーションがありふれた例外で停止することについてどう思いますか?

  • 医療機器
  • 発電所
  • 侵入検知システム

try / catch でキャッチしている例外については、実際にそれらを予期して処理する必要があります。他のすべてのケースでは、予測された実行レベルにすばやく失敗することをお勧めします。では、ネットワークまたは Web ハンドラーを使用している場合、現在の操作を終了させないのはなぜでしょうか? アプリ全体をダウンさせる必要がありますか?

ミッション クリティカルでパブリック インターフェイスを持つアプリを開発している場合、これはますます重要になります。アプリをダウンさせる可能性のある例外が利用可能な場合、それは、サービス拒否攻撃を引き起こすことを意図したブラックハット ハッカーの攻撃のベクトルになります。

この戦略を悪用するエッジケースは、あまり賞賛するには大きすぎます。はるかに優れたアプローチは、ドメインの問題を解決することです。この戦略が何を目指しているのかを理解し、適切な部分を問題に適用してください。

警告: 私は稼働時間とセキュリティが重要なサーバー側システムで作業しています。

編集:「プロセスダイ」の意味に混乱したと思います-これはアプリ全体または実行中のスレッドなどへの参照でしたか?

于 2009-02-23T06:43:46.877 に答える
6

これは非常にマイクロソフトです。

MS は、ハンドルされていないすべての例外を WER にスローすることを望んでいます。(Windows エラー報告。アプリがクラッシュしたときに Microsoft にエラーを送信するためのダイアログ)

そうすることで、使用状況の指標を取得し、顧客の不満の原因となっている主要な未処理の例外に集中できます。例外がどこから来るのかを考えるように強制するという考えだと思います。

しかし、私はあなたに心から同意します。後で再スローしても、常にルートで未処理をキャッチし、何が起こったかをログに記録します。これに関する唯一の問題は、未処理のexがメモリ不足である場合です。その場合、JITがこれ以上メモリを割り当てることができないため、logへの呼び出しが失敗する可能性があります.C++プログラムは、メモリのバブルを取得することでこれを処理すると思います.未処理の例外でそれを解放し、非常にタイトなログルーチンを実行して、正常に試行して失敗します。

于 2009-02-23T04:39:22.903 に答える
3

私はリヒターの資料に精通していませんが、哲学/正当化は、ほとんどの場合、プログラムが未処理の予期しない例外から回復するためにできることは何もないということだと思います.

しかし、ユーザーの目の前でプログラムを終了させるのはあまり良い考えではありません。非常に悪い印象を残してしまいます。私は、未処理の例外をデータベースに記録し、開発者に通知し、それらを追跡して確実に修正することを好みます。

繰り返しになりますが、私はまさにその目的のために製品を販売しているので、この分野では少し偏っています!

于 2009-02-23T04:39:43.777 に答える
3

問題を適切に処理できない場合、そしてそれがなんらかの形式 (ディスクまたは Web から読み取ろうとしたものを含む) の不適切な入力を拒否する以外の場合は、おそらく処理できません。その場合、死ぬ必要があります。安全に続行できると 100% 確信している場合を除き、使用しないでください。

しかし、私は単純に例外を手放すつもりはありません。それを捕まえて、できるだけ多くの情報を収集してください。あなたのプログラムがある種のドキュメントを操作し、それを新しい名前で保存する場合、それは破損している可能性があり、オリジナルを上書きしたくありません。

于 2009-02-23T04:59:30.093 に答える
2

スタック トレースほどユーザーの信頼を損なうものはありません。少なくとも、例外をキャッチして、できるだけ多くの情報をログに記録してください。次に、問題を回避するか、問題をサポートに報告するために何をすべきかについて、わかりやすいメッセージと指示をユーザーに提供します。

ここでは、不確定な状態が続くことに懸念があります。これが Web アプリの場合、セッションとアプリの状態に過度に依存しない限り、これは問題になりません。これが Windows アプリの場合は、自由に終了してください (ユーザーに保存する機会を与えた後)。

于 2009-02-23T06:18:00.887 に答える
2

Exception のすべてのサブクラスが何であるかがわからないため、それらをキャッチしても問題ないかどうかを単純に知ることはできません。したがって、自分のビジネスに気を配る必要があります。知っていて気にかけている例外をキャッチします。これは主に、自分のプログラム用に明示的に作成したもの、または使用しているライブラリ呼び出しからのエラーに対して作成されたものです。特に、Exception クラスをキャッチすることは、単に怠惰で悪いプログラミングです --- 基本的に、あなたは「問題が何であるかは気にせず、教えずに、これを実行してください」と言っているのです。Java プログラムがどのように例外を処理するかを見てみましょう。そこでの例外処理の慣行は通常、非常に優れています。

于 2009-02-23T09:47:44.080 に答える
1

顧客は何を期待していますか?

それはすべてそれに戻ります。顧客がプログラムの停止を処理でき、再起動できる場合は、それで問題ありません。

場合によっては、プロセスを終了させて​​、別のプロセスを作成してリクエストを処理する方がよい場合があります。

場合によっては、問題の解決を試みたほうがよい場合があります。

于 2009-02-23T04:40:03.087 に答える
1

常にルート例外キャッチャーが必要だと言います...特に、何が問題だったのか、コードなどを示す何らかの情報を例外に収めて、ユーザーに出力できる場合は特にそうです。次に、ユーザーはいつでもあなた (またはサポートなど) に、「保護違反でクラッシュした」のではなく、何が問題なのかを尋ねて、いくつかの情報を提供できます。

于 2009-02-23T04:43:06.433 に答える
1

例外をまったく処理しないという利点が 1 つあります。問題が発生した場合は、プログラムを不確定な状態で継続させるのではなく、クラッシュさせてユーザーから苦情を申し立てる方がよいでしょう。

たとえば、リアルタイム トレーディング システムを作成していて、予期しないエラーが発生した場合は、システムをクラッシュさせたほうがよいでしょう。そうしないと、プログラムが継続して愚かな取引を行う可能性があります。ユーザーはすぐに「なんてこと?」と文句を言うでしょうが、少なくとも何百万ドルも失うことはありません。

于 2009-02-23T06:05:42.430 に答える
1

特にSimucalによる素晴らしい回答がすでにここにあります。ポイントを追加したいだけです:

攻撃的なプログラミングは、デバッグに最適です。私の経験では、「早期に失敗し、頻繁に失敗する」ことは、コードにバグのトラップを設定するようなものと考えることができます。何か問題が発生した場合 (メモリ リーク、メモリ ストンプ、予期しない NULL など)、プログラムがすぐに失敗した場合 (コールスタックなどのデバッグ データが関連付けられている場合) は、通常、問題を発見するのがはるかに簡単です。

防御的プログラミングは、本番環境に最適です。アプリケーションが出荷された後、「foo() で未処理の例外」という素敵な小さなダイアログをエンドユーザーに表示したくない場合があります。アプリがベータ版で、まだデバッグ情報を収集している場合、これは素晴らしいことかもしれませんが、安定したアプリを出荷している場合は、何かが失敗するというまれなケースで、ユーザーに不可解な出力で煩わされたくないだけかもしれません.

両方の方法で使用できる場合もあります。私はしばしば次の行に沿って C コードを書きました。

void foo(char* data) {
    ASSERT(data);
    if (!data) { return; }
    // ... work with data
}

このコードをテスト環境でコンパイルすると、assert ステートメントがエラー状態をトラップします。実稼働環境でコンパイルされた場合、アサートはプリプロセッサによって削除され、foo() は暗黙のうちに失敗します。

例外はアサートよりも表現力と柔軟性に優れており、アプリケーションがテスト環境で早期に失敗し、運用環境でエラーをログに記録している間はうまく動作しないように、例外を管理するさまざまな方法があります。プロジェクトの種類によっては、この種の設計が適切な場合があります。

于 2009-02-23T09:05:56.367 に答える
0

すべてをキャッチしようとすることの問題は、回復方法がわからないものを「処理」することになることが多いことです。ユーザーは物事が順調に進んでいるという誤った印象を受けますが、内部的にはスイスチーズに目を向け、最終的には非常に奇妙な方法で壊れます.

一方、ユーザーに例外をスローしても、ユーザーに報告する方法がない場合はそれほど役に立ちません。

  • MS に登録すると、新しい Windows サービスがその機能を提供します。
  • drwatson をインストールすると、ユーザーが手動で送信するデータ (ダンプ ファイル) をキャプチャすることもできます。

サービスライブラリを提供し、それがプロセス内で実行されている場合、サービスがサーバー全体を混乱させてメモリや設定を台無しにする場合など、例外が発生したときにサーバーをシャットダウンする必要がある可能性があります。

契約により、API は「これを実行できますか」と言う方法と「実行する」方法を提供する傾向があります。また、MS ファイル オープンのような多くの API では、例外を発生させてエラー コードを返すように切り替えることができます。

于 2009-02-23T05:43:57.613 に答える
0

カスタム エラー ハンドラーをいつでもセットアップして、処理する準備ができていない例外のキャッチを無視することができます。適切な条件が満たされている場合、不明な点から回復しようとすると、マイナスの結果が生じる可能性もあります。しかし、繰り返しになりますが、それは実際には例外が何であるか、およびそれらをどのように処理しているかによって異なります。

一方で、人々は「例外は悪だ」という考え方に圧倒されていると思います。それらはツールであり、適切に使用すれば、驚くべき特典を得ることができます。ただし、root を catch(Exception) でラップして悪用する人が多くいます。

于 2009-02-23T06:05:12.167 に答える