3

私は、例外をスロー/再スローするインスタンスを処理しましたが、それを囲むコードが特定の例外をキャッチすることを知っていました。しかし、例外がキャッチされないことを知って、例外をスローしたいときはありますか?

または、少なくとも、例外をキャッチしませんか?

例外は、正しく処理されない限り、すぐにアプリケーションを停止しますか?だから私はあなたがあなたのアプリケーションを故意に死なせたいと思うかどうか尋ねていると思いますか?

4

14 に答える 14

15

アプリケーションが主に他のクライアントによって使用され、スタンドアロンではない場合、処理方法がわからない (または処理したくない) 状況が発生した場合に例外をスローすることは一般的に理にかなっています。あなたがそこから立ち直る方法。クライアントは、スローされる可能性のある例外をどのように処理するかを決定できる必要があります。

一方、アプリケーションエンドポイントである場合、例外をスローすることは、本質的に、何かがひどく間違っていることを人々に警告する通知メカニズムになります。このような場合、いくつかのことを考慮する必要があります。

  • アプリケーションの継続的な実行はどの程度重要ですか? このエラーは本当に回復不能ですか? 例外をスローしてプログラムを終了することは、スペース シャトルで行いたいことではありません。

  • 実際のロギングのプロキシとして例外を使用していますか? これを行う理由はほとんどありません。代わりに、実際のロギング メカニズムを検討してください。例外をキャッチし、ロガーに何が起こったのかを解決させます。

  • 自分で例外をスローして何を伝えようとしていますか? 新しい例外をスローすることの価値を自問し、必要なことを行うためのより良い方法がないかどうかを慎重に検討してください。

  • 例外をキャッチしないと、リソースが悪い状態のままになる可能性があります。適切に終了しないと、通常はクリーンアップされません。これを行う必要がある場合は、自分が何をしているのかを理解していることを確認してくださいtry-finally.

于 2009-03-20T15:42:09.120 に答える
8

少し前に出会った非常に優れたルールがあります。

メソッドがその名前が示すことを実行できない場合、例外をスローします。

例外は、何か問題が発生したことを示しているという考え方です。メソッドを実装するとき、それが正しく使用されるかどうかを認識するのはあなたの責任ではありません。メソッドを使用するコードが例外をキャッチするかどうかは、あなたの責任ではなく、メソッドを使用する人の責任です。

従うべきもう 1 つの規則は次のとおりです。

何をしたいのかわからない限り、例外をキャッチしないでください。

明らかに、クリーンアップ コードを try...finally ブロックに含める必要がありますが、例外をキャッチするためだけに例外をキャッチするべきではありません。また、例外を黙って飲み込んではいけません。(C# で catch (Exception ex) を実行するなどして) すべての例外をキャッチする必要がある場合もありますが、これは一般的ではなく、一般的に非常に特殊な技術的な理由があります。たとえば、.NET 2.0 以降でスレッドを使用している場合、スレッドから例外がエスケープされると、アプリケーション ドメイン全体がアンロードされます。ただし、このような場合は、最低限、例外の詳細をエラーとしてログに記録し、コメントで説明を提供する必要があります。

于 2009-03-20T16:15:01.087 に答える
5

もちろん。たとえば、Java でいくつかのバイトを文字列にロードしようとしている場合:

try {
  String myString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
  // Platform doesn't support UTF-8?  What is this, 1991?
  throw new RuntimeExceptione(e);
}

この場合、グレースフル デグラデーションはなく、プラットフォームは必要な操作をサポートできません。初期化時にこの状態を確認することはできますが、String のコンストラクターは依然としてこの例外をスローするため、対処する必要があります。それか、または Charset.forName() を使用してください:)

于 2009-03-20T15:55:48.247 に答える
5

通常、アプリケーションの初期の反復では例外をキャッチしません。多くの場合、例外からの回復には何らかのビジネス ルールが必要ですが、多くの場合、それらのビジネス ルールは定義されていません。アプリケーションを停止させるのではなく、例外を「処理」する場合は、顧客のためにビジネス ルールを考案することになります。良くない。

例外をキャッチするためだけにすべての例外をキャッチするという一般的なパターンは、数えきれないほどの頭痛の種になりました。通常、誰かが何らかの一般的な例外処理コードをアプリケーション全体に配置することが起こります。これにより、必然的にバグが隠されたり、望ましくない動作が作成されたりします。(ちなみに、キャッチして再スローしないのはさらに悪いことです。)

そのため、代わりに「いつ例外をキャッチする必要がありますか?」と尋ねることをお勧めします。

于 2009-03-20T16:09:07.370 に答える
3

これが問題です...それは「レイヤー」、または「カプセル化」、または「低結合」についてです。コードベースのある場所で、何かを行うメソッドを作成しています。それがパブリックメソッドだとしましょう。したがって、呼び出し元について多くのことを仮定するべきではありません...むしろ、誰が呼び出しているか、呼び出し元がどのような状況にあるかに関係なく、本来の仕事を行うだけです。

そして、何らかの理由でジョブを完了できない場合は、発信者に「申し訳ありませんが、それができませんでした。その理由は次のとおりです」と伝える必要があります。例外は、呼び出し元にそれを伝えるための優れたメカニズムです (唯一のメカニズムではありませんが、ほとんどの場合でこれまでに見た中で最高のメカニズムです)。

したがって、例外をスローすると、それがキャッチされるかどうかわかりません...パブリックメソッドを公開していて、誰がそれを呼び出すことを選択するのか、そしてその理由がわからないためです。

例外のキャッチは「コンテキスト」の仕事です。たとえば、例外をスローする可能性のあるパブリック メソッドを含むライブラリを作成しているとします。次に、そのライブラリを Windows フォーム アプリから使用しているとします。Windows フォーム アプリは例外をキャッチし、ユーザーにメッセージ ボックスを表示する場合があります。

ただし、後で、Windows サービスから同じライブラリを使用する可能性があります。サービスは、例外をキャッチしてログに記録し、元の呼び出し元にエラーを返す可能性が高くなりますが、さらに要求を処理できるように実行を続けます。

したがって、例外は、呼び出し元とプロバイダーの間の契約上の合意のようなものです。プロバイダーは、「私がその仕事をするか、できない理由をあなたに話します。そこから何をするかはあなた次第です」と言います。電話の相手は、「その仕事ができない場合は、その理由を教えてください。その場合の対応は私が決めます」と言います。

于 2009-03-20T16:26:26.613 に答える
1

しかし、例外がキャッチされないことを知って、例外をスローしたいときはありますか?

手動で例外をスローしている場合、ほとんどの場合、例外がキャッチされるかどうかはわかりません。キャッチされることがわかっている場合は、最初に例外をスローするのではなく、自分で処理することができます。

公平を期すために、それはあなたが行っているプログラミングの種類に部分的に依存していると思います、そして時々同じプログラマーがライブラリとそのライブラリを消費するコードの両方を構築することになります。

例外をキャッチしませんか?

予期していなかった/気づかなかった場合は、例外がスローされる可能性があります。しかし、それを脇に置いて、例外を認識していると仮定すると、ある層でそれについて知っているが、次の層がそれを処理するためのより適切な場所であることを知っている場合があります。

于 2009-03-20T15:37:00.490 に答える
1

まず、例外をキャッチしない方がよい状況が絶対にあります。

例外によって、プログラムが不明な状態にあることがわかる場合があります。例外の種類を考えると、これが本質的に真である例外がいくつかあります。ANullReferenceExceptionは基本的に「バグがある」ことを示します。そして、そのような例外をキャッチすることで、バグを隠すことができます。これは短期的には良さそうに思えますが、長期的にはバグを修正したほうがよいでしょう。製品がクラッシュすることはないかもしれませんが、期待どおりの動作をしないことは確かです。

しかし、これは私たちが独自に発明した例外タイプにも当てはまります。場合によっては、例外 A がスローされたという事実は「不可能」であるはずですが、実際に発生してしまった場合、バグが発生します。

また、例外をキャッチすると、非常に重要なことが起こります。tryfinallyブロック内のコール スタック全体のブロック (およびそれが呼び出すもの) が実行されます。それらの最終ブロックは何をしますか? まあ、何でも。そして、プログラムが不明な状態にある場合、私は本当に何でもします. 貴重な顧客データをディスクから消去する可能性があります。彼らはより多くの例外をスローする可能性があります。メモリ内のデータが破損し、バグの診断が不可能になる可能性があります。

したがって、例外が不明な状態を示している場合は、これ以上コードを実行したくないので、何をするにしても例外をキャッチしないでください。問題が発生すると、プログラムは無害に終了し、Windows エラー報告は、問題が最初に検出されたときのプログラムの状態をキャプチャできるようになります。例外をキャッチすると、より多くのコードが実行され、プログラムの状態がさらに悪化します。

第二に、キャッチされないことを知って例外をスローする必要がありますか? その質問は再利用可能なメソッドの性質を誤解していると思います。メソッドの全体的な考え方は、それが従う「契約」を持っているということです。特定のパラメーターを受け入れ、特定の値を返し、さらに特定の条件下で特定の例外をスローします。それがコントラクトです - それをどうするかは発信者次第です。呼び出し元によっては、例外 A が回復可能な状態を示している場合があります。他の呼び出し元の場合、バグを示している可能性があります。そして、上で述べたことから、例外がバグを示している場合、それをキャッチしてはならないことは明らかです。

そして、これがMicrosoft Enterprise Library の Exception Handling Blockにとって何を意味するのか疑問に思っているなら、はい、かなり壊れています。彼らはあなたに指示catch (Exception x)し、あなたのポリシーに基づいて再スローするかどうかを決定します。遅すぎる -finallyブロックはその時点までにすでに実行されています。そうしないでください。

于 2009-03-20T15:57:34.153 に答える
1

アプリケーションの種類によって異なります。例外が実行コンテキストに到達した後でも、Web アプリケーションは引き続き実行できます。

処理できないレベルで例外をキャッチした場合、例外を「スロー/再スロー」するのが一般的です。ただし、ほとんどの場合、問題にコンテキストを追加します。少なくとも、問題がキャッチされて再スローされたことを示すために、より高いレベルでログを追加します。

例えば

A が B を呼び出して C を呼び出す (例外をスローする)

B キャッチ/リスロー

Aがキャッチ。

この場合、B がエラーを生成してスローすることと、C がエラーを生成してスローすることを区別できるように、B にログを追加する必要があります。これにより、後で問題をデバッグして修正する能力が向上します。

一般に、プログラムを強制終了するために例外が必要になることはほとんどありません。ベスト プラクティスは、例外をキャッチして正常に終了することです。これにより、現在開いている情報を保存し、使用中のリソースを解放して、破損しないようにすることができます。終了する場合は、致命的な例外をキャッチしたときに実行していたことを含む独自の「コア ダンプ」情報レポートを作成できます。

例外によってプロセスが強制終了されると、カスタム調整されたクラッシュ情報を取得する機会がなくなります。また、わかりやすいエラー メッセージをユーザーに提供して終了する部分もスキップされます。

したがって、常に例外をキャッチし、自発的にプログラム内でそれらを暴走させないことをお勧めします。

編集

ライブラリを作成している場合は、関数が例外をスローするか、例外セーフにするかを事前に選択する必要があります。そのような場合、例外をスローし、呼び出し元がそれをキャッチするかどうかわからないことがあります。ただし、その場合、関数が例外をスローできることを API が宣言している限り、それをキャッチすることはあなたの責任ではありません。(「例外をスローする可能性がある」という意味の単語を探しています...誰か知っていますか?一日中悩まされます。)

于 2009-03-20T15:39:34.180 に答える
0

それはあなたが「捕まる」とはどういう意味かによります。何か、どこかで、それが基盤となるOSであるか他の何かであるかにかかわらず、最終的に例外をキャッチします。

個々のジョブで構成されるジョブプランを実行するワークフローシステムがあります。各ジョブはコードの単位を実行します。一部の例外については、コードでそれらを処理したくないが、外部ワークフローシステムがそれをキャッチするようにスタックにスローします(これは完全にスローアーのプロセスの外で発生します)。

于 2009-03-20T15:43:51.207 に答える
0

アプリケーション全体を作成している場合、その理由はあなた自身のものです。例外をスローしてアプリを停止させたいと思うかもしれないいくつかの状況を考えることができますが、それらのほとんどはあまり良い理由ではありません。

最良の理由は通常、デバッグ時です。デバッグ中に例外を頻繁に無効にして、どこで失敗しているのかをよりよく知ることができるようにします。デバッガーを備えたマシンで実行している場合は、デバッガーでスローされた例外ブレークをオンにすることもできます。

もう1つの考えられる理由は、例外がスローされた後に続行しても意味がないか、回復不能なデータ破損またはさらに悪い結果になる可能性がある場合です(レーザービームを備えたロボットを考えてみてください。ただし、アプリケーションがこれらの状況IMOに対処し、クラッシュすることを確認する必要があります。プログラムはただ怠惰な方法です)。

自分で使用しないAPIコードまたはフレームワークコードを作成している場合、誰かがあなたの例外をキャッチするかどうかはわかりません。

于 2009-03-20T15:48:44.050 に答える
0

うん、サービス/オブジェクトを消費している開発者を平手打ちして、「Ur dO1n it WrOnG!!!!」と伝える唯一の機会です。

それと、許可したくない、または一見「不可能」に見える可能性を取り除くことです。すべての例外をキャッチして続行するアプリは、カオスに囲まれた壁に囲まれた庭にすぎません。

于 2009-03-20T15:57:03.767 に答える
0

エンドユーザーが見ることができる場所に例外がキャッチされないようにすることはおそらく望ましくありませんが、多くの場合、API のクライアント (他のプログラマー) に例外の処理方法を決定させることは許容されます。

たとえば、Java クラス ライブラリを設計しているとします。String を受け取る public メソッドを公開します。アプリケーションでは、null の入力値によってエラーが発生します。自分でエラーを処理する代わりに、null 値をチェックしてから IllegalArgumentException をスローすることもできます。

もちろん、この状況でメソッドがこの例外をスローすることを文書化する必要があります。この動作は、メソッドのコントラクトの一部になります。

于 2009-03-20T15:41:33.273 に答える
0

私が一貫した方法であると信じている方法で何らかの方法でデータを処理している、適度に大きなシステムが必要な場合。

どこかで、アプリケーションの状態が矛盾していることに気付きました。

システムは、不整合を修正して正常に回復する方法を (まだ) 認識していません。

次に、はい、可能な限り詳細な例外をスローし、アプリケーションをできるだけ早く終了させて​​、データにそれ以上の害を及ぼさないようにします。回復できる場合は、混乱を隠蔽するために弱々しく試みて問題を悪化させないことが重要です.

その後、不整合の原因となった一連のイベントがよりよく理解されると、より高度な機能でその例外をキャッチし、状態を修復し、中断を最小限に抑えて処理を続行できます。

于 2009-03-20T17:31:09.903 に答える
0

ライブラリは、アプリケーション コードによって発生を許可されるべきではない状態が発生した場合、防御的なプログラミング チェックに基づいて例外をスローすることがよくあります。多くの場合、アプリケーション コードは、これらの無効な条件のほとんどが発生しないように記述されているため、例外がスローされることはありません。したがって、それらをキャッチしても意味がありません。

言語によっては (私は主に C# ではなく C++ の観点から考えており、違いが何であるかは明確ではありません)、キャッチされない例外が実際にスローされた場合の影響は、例外が発生する前の時代に行われていたものとおそらく同じです。発明されました。たとえば、C ライブラリでの防御的プログラミングの一般的なポリシーは、エラー メッセージを表示してプログラムをすぐに終了することでした。

違いは、例外のスローが可能であることが判明した場合 (これは単体テストによって発見されることを願っています)、より建設的な方法で問題から回復できる例外ハンドラーを追加することが比較的簡単であることが多いということです。例外をスローする呼び出しが行われる前に条件が発生しないようにするために、ライブラリを書き直したり、アプリケーション コードに複雑なチェックを追加したりする必要はありません。

キャッチされない例外スローがかなりあります。それらはすべて防御目的のためのものであり、キャッチされないことは実際に発生する例外にとっては悪いことですが、これは開発とテスト中にのみ発生し、これまでアプリケーション コードで考慮できなかったエラー条件が発生します。そして、それが発生した場合、修正がぎこちなくなることはめったにありません-大規模なリファクタリングの必要はなく、エラー状態チェックでアプリケーションコードを非常に複雑にする必要はなく、比較的単純な回復または "ごめんなさい、デイブ、残念ながらそれはできません。」アプリ全体を失敗させることなく。

于 2011-01-02T23:35:00.680 に答える