32

一般的な知恵では、本当に例外的な条件に対してのみ例外を使用するように言われていることを理解しています (実際、ここ SO で何度かその声明を見てきました)。

ただし、Krzysztof Cwalina は次のように述べています。

例外に関する最大の誤解の 1 つは、それらが「例外的な条件」のためのものであるということです。実際には、それらはエラー状態を伝えるためのものです。フレームワーク設計の観点からは、「例外的な条件」などというものはありません。条件が例外的であるかどうかは、使用状況によって異なりますが、再利用可能なライブラリは、それらがどのように使用されるかをほとんど知りません。たとえば、単純なデータ入力アプリケーションの場合、OutOfMemoryException は例外的な場合があります。独自のメモリ管理を行うアプリケーション (SQL サーバーなど) にとっては、それほど例外的ではありません。言い換えれば、ある人の例外的な状態は別の人の慢性的な状態です.

彼はまた、例外は次の目的で使用する必要があると述べています。

  • 使用上の誤り
  • プログラムエラー
  • システム障害

Krzysztof Cwalina が MS の CLR チームの PM であることを考えると、彼の発言についてどう思いますか?

4

15 に答える 15

26

これは単純すぎるように聞こえますが、適切な場合に単純に例外を使用することは理にかなっていると思います。Java や Python などの言語では、特に特定の状況で、例外が非常に一般的です。例外は、コード パスを介してバブルアップし、開発者に明示的にキャッチするよう強制するエラーの種類に適しています。私自身のコーディングでは、エラーを無視できない場合、または関数呼び出しなどにエラー値を返す代わりに例外をスローする方が単純な場合に、例外を追加する適切なタイミングを検討しています。

私がすぐに思いつく例外の最も適切な場所のいくつかは次のとおりです。

  • NotImplementedException - 何もせずに単に戻るのではなく、特定のメソッドまたは関数が使用できないことを示す非常に適切な方法。
  • OutOfMemory例外 - このタイプのエラーを処理するより良い方法を想像するのは困難です。これは、プロセス全体または OS 全体のメモリ割り当てエラーを表すためです。もちろん、これは対処するために不可欠です!
  • NullPointerException - null 変数へのアクセスはプログラマーのミスです。IMO これは、エラーを強制的に表面化させるもう 1 つの良い場所です。
  • ArrayIndexException - C のような容赦のない言語では、バッファ オーバーフローは悲惨です。より適切な言語は、一部の型の null 値を返すか、一部の実装では、配列をラップすることさえあります。私の意見では、例外をスローする方がはるかにエレガントな応答です。

これは決して包括的なリストではありませんが、要点を示していることを願っています。エレガントで論理的な例外を使用します。プログラミングの常として、適切な仕事のための適切なツールは良いアドバイスです。何もせずに例外に夢中になる意味はありませんが、自由に使える強力でエレガントなツールを完全に無視するのも同様に賢明ではありません。

于 2008-10-08T00:41:59.583 に答える
11

フレームワークを書いている人にとっては、興味深いかもしれません。

私たち以外にとっては、混乱を招きます (そしておそらく役に立たないでしょう)。通常のアプリケーションでは、例外は「例外的な」状況として脇に置く必要があります。例外は、プログラムの通常の順次表示を中断します。

プログラムの通常の上から下への順次処理を壊さないように注意する必要があります。例外処理は、意図的に読みにくくなっています。したがって、標準シナリオ外のものについては例外を予約してください。

例: ユーザー入力の検証に例外を使用しないでください。人は常に入力ミスをします。それは例外ではありません。それが私たちがソフトウェアを書く理由です。それがif文の目的です。

アプリケーションが OutOfMemory 例外を受け取った場合、それをキャッチしても意味がありません。それは例外的です。「順次実行」の前提は窓の外にあります。あなたのアプリケーションは運命づけられています。クラッシュするだけです。クラッシュする前に RDBMS トランザクションが終了することを願っています。

于 2008-10-08T00:25:04.077 に答える
9

プログラムでの例外の使用を正当化する「例外条件」を正確に解釈するものを知ることは実際には困難です。

エラーの原因を伝えるのに非常に役立つ 1 つのインスタンス。Krzysztof Cwalina からの引用が言及しているように:

例外に関する最大の誤解の 1 つは、それらが「例外的な条件」のためのものであるということです。実際には、それらはエラー状態を伝えるためのものです。

具体的な例を挙げるとgetHeader(File f)、ファイルからヘッダーを読み取り、オブジェクトを返すメソッドがあるとしFileHeaderます。

ディスクからデータを読み取ろうとすると、いくつかの問題が発生する可能性があります。おそらく、指定されたファイルが存在しない、ファイルに読み取れないデータが含まれている、予期しないディスク アクセス エラー、メモリ不足などがあります。失敗の原因が複数あるということは、何が問題なのかを報告する方法が複数あるということです。

例外が使用されていないが、発生したエラーの種類を現在のメソッド シグネチャで伝える必要がある場合は、null. を取得してnullもあまり情報が得られないため、その結果から得られる最良のコミュニケーションは、「何らかのエラーが発生したため、続行できませんでした。申し訳ありません」ということです。-- エラーの原因を伝えていません。

(または、FileNotFound 条件などを示す FileHeader オブジェクトのクラス定数を使用して、エラー コードをエミュレートすることもできますが、これは、 、 、 のブール型を持つことの悪臭を放ちTRUEますFALSEFILE_NOT_FOUND )

FileNotFoundor例外 (仮説) が発生した場合DeviceNotReady、少なくともエラーの原因がわかり、これがエンド ユーザー アプリケーションである場合は、問題を解決する方法でエラーを処理できます。

例外メカニズムを使用すると、通常の実行フロー内にない状態を通知するためにエラー コードを使用するためのフォールバックを必要としない通信手段が得られます。

ただし、それはすべてが例外によって処理される必要があるという意味ではありません。S.Lottが指摘したように:

たとえば、例外を使用してユーザー入力を検証しないでください。人は常に間違いを犯します。それがif文の目的です。

これはいくら強調してもしすぎることはありません。例外をいつ使用すべきか正確にわからないことの危険性の 1 つは、例外を喜んで受け入れる傾向があることです。入力の検証で十分な例外を使用します。

InvalidUserInputこのような状況に対処するために必要なのは、入力として期待されるものをユーザーに通知することだけである場合、例外を定義してスローしても意味がありません。

また、ユーザー入力には、ある時点で誤った入力があることが予想されることに注意してください。これは、外部からの入力をプログラムの内部に渡す前に、入力を検証するための防御策です。

何が例外的で何がそうでないかを判断するのは少し難しいです。

于 2008-10-08T01:02:05.190 に答える
6

私は通常、Python でプログラミングを行っており、その言語では例外がどこにでもあるため、私にとって例外は、システム エラーから完全に正当な状態まで、あらゆるものを表している可能性があります。

たとえば、文字列に整数が含まれているかどうかを確認する「pythonic」な方法は、int(theString) を試して、例外が発生するかどうかを確認することです。それは「例外的なエラー」ですか?

繰り返しますが、Python では、for ループは常に反復子に作用すると考えられており、反復子はジョブを終了するときに 'StopIteration' 例外を発生させる必要があります (for ループはその例外をキャッチします)。それは果たして「例外的」なのだろうか。

于 2008-10-08T00:47:48.480 に答える
3

「教えて、聞かないで」を実践する場合、例外は、プログラムが「それはできません」と言う方法です。「X を実行する」と言っても、X を実行できないという点で「例外的」です。単純なエラー処理状況。一部の言語では、この方法で作業するのが非常に一般的です。Java と C++ では、例外が非常にコストがかかるため、人々は別の意見を持っています。

一般: 例外は単に「できない」ことを意味します

実用的: ... 自分の言語でそのように作業する余裕がある場合。

市民権: ... そしてあなたのチームはそれを許可します。

于 2008-10-31T14:57:42.097 に答える
3

地面に近いほど、エラー通信の手段としての例外は適切ではないと思います。Java や .net などの高度な抽象化では、呼び出し元にエラー メッセージを渡す洗練された方法として例外が作成される場合があります。ただし、これは C には当てはまりません。これは、フレームワークと API の設計上の決定でもあります。

于 2008-10-08T00:54:12.553 に答える
2

例外の定義は次のとおりです。例外とは、プログラムの実行中に発生し、プログラムの命令の通常の流れを中断するイベントです。

したがって、あなたの質問に答えるには、いいえ。例外は、例外的な場合とそうでない場合がある、破壊的なイベントの場合です。私はこの定義が大好きです。私のように例外を受け入れれば、シンプルでいつでも機能します。たとえば、ユーザーが間違った un/pw を送信したか、不正な引数/不適切なユーザー入力がありました。ここで例外をスローすることは、これらの問題を解決する最も簡単な方法です。これらの問題は混乱を招きますが、例外的ではなく、予期せぬものでもありません。

それらはおそらく混乱と呼ばれるべきでしたが、そのボートは出航しました。

于 2015-07-23T15:40:01.920 に答える
2

予期しない問題をキャッチするために例外を使用する必要があるのには、いくつかの正当な理由があると思います。

まず、例外をカプセル化するオブジェクトを作成します。これは、定義により、単純な if ステートメントを処理するよりもはるかにコストがかかる必要があります。Java の例として、FileNotFoundException を定期的に予期して処理するのではなく、File.exists() を呼び出す必要があります。

第 2 に、現在のメソッド (または場合によってはクラス) の外部で例外がキャッチされると、処理がすべて 1 つのメソッド内にある場合よりもコードが読みにくくなります。

そうは言っても、私は個人的に例外が大好きです。これらを使用すると、発生する可能性はあるが発生しない可能性が高い型エラーのすべてを明示的に処理する必要がなくなります。これにより、print-an-error-and-abort-on-non-zero-return-すべてのメソッド呼び出しのコード処理。

私の結論は... それが起こると合理的に期待できるなら、それはあなたのアプリケーションの一部であり、あなたはそれのためにコーディングするべきです. それ以外は例外です。

于 2008-10-08T01:03:10.397 に答える
1

私はこれについて疑問に思っていました。「例外的」とはどういう意味ですか? 厳密な定義はないかもしれませんが、特定のコンテキストで何が例外的かを判断するために使用できる経験則はありますか?

たとえば、「例外的な」条件とは、関数の契約に違反する条件であると言えますか?

于 2008-10-08T00:35:46.910 に答える
0

彼は正しいと思います。Javaでの数値解析を見てください。解析する前に入力文字列をチェックすることさえできません。何か問題が発生した場合は、NFE を解析して取得する必要があります。解析の失敗は例外的なものですか? 違うと思う。

于 2011-05-25T21:41:20.227 に答える
0

結局のところ、仕事をするためにどのツールが必要かということです。

例外は非常に強力なツールです。それらを使用する前に、このパワーとそれに伴う複雑さが必要かどうかを尋ねてください。

例外のある行にヒットするとすべてが停止することがわかっているため、例外は単純に見えるかもしれません。ここからどうなりますか?

キャッチされない例外は発生しますか?

例外はグローバル エラー処理によって捕捉されますか?

例外は、よりネストされた詳細なエラー処理によって処理されますか?

その例外が何をするかを知るには、スタックのすべてを知る必要があります。これは、独立の概念に違反しています。そのメソッドは、エラー処理に依存して、期待どおりに動作するようになりました。

メソッドがある場合、そのメソッドの外にあるものを気にする必要はありません。入力が何であるか、それを処理する方法、および応答を返す方法だけを気にする必要があります。

あなたが本質的に言っている例外を使用するとき、私はここから何が起こるかは気にしません。

エラーの処理方法が気になる場合は、もう少し考えて、それをメソッドのインターフェイスに組み込みます。たとえば、オブジェクトを見つけようとしている場合、オブジェクトが見つからない場合は、そのオブジェクトのデフォルトを返す可能性があります。 「オブジェクトが見つかりません」のような例外をスローするよりも。

エラー処理をメソッド インターフェイスに組み込むと、そのメソッドのシグネチャがそのメソッドの機能をより明確にするだけでなく、メソッドの呼び出し元にエラーを処理する方法の責任が課せられます。呼び出し元のメソッドはそれを処理できる場合とできない場合があり、そうでない場合はチェーンを再度報告します。最終的に、アプリケーションのエントリ ポイントに到達します。アプリケーションのパブリック インターフェイスを使用している場合は、例外がどのように処理されるかをよく理解しているため、ここで例外をスローするのが適切です。

Web サービスのエラー処理の例を挙げましょう。

レベル 1. global.asax でのグローバル エラー処理 - これは、キャッチされない例外を防ぐセーフティ ネットです。これは、意図的に達成されるべきではありません。

レベル 2. Web サービス メソッド - json インターフェースに常に準拠することを保証するために、try/catch にラップされます。

レベル 3. ワーカー メソッド - データを取得して処理し、そのまま Web サービス メソッドに返します。

ワーカー メソッドで例外をスローするのは適切ではありません。はい、Web サービス メソッドのエラー処理をネストしましたが、そのメソッドは、これが存在しない可能性がある他の場所で使用できます。

代わりに、ワーカー メソッドを使用してレコードを取得し、レコードが見つからない場合は、単に null を返します。Web サービス メソッドは応答をチェックし、null を検出すると、続行できないことを認識します。Web サービス メソッドは、json を返すエラー処理があることを認識しているため、例外をスローすると、何が起こったかの詳細が json で返されます。クライアントの観点からは、簡単に解析できる json にパッケージ化されたことは素晴らしいことです。

各ピースが何をする必要があるかを知っていて、それを実行していることがわかります。ミックスで例外をスローすると、アプリケーション フローがハイジャックされます。これにより、コードの追跡が困難になるだけでなく、例外の悪用に対する応答が try/catch になります。これで、別の非常に強力なツールを悪用する可能性が高くなります。

アプリケーションの途中で try/catch がすべてをキャッチしているのをよく見かけます。これは、使用するメソッドが見た目よりも複雑であることに開発者が恐れたためです。

于 2015-06-25T21:28:35.033 に答える
0

例外的な条件がある場合にのみ、例外を使用する必要があると私は確信しています。

問題は「例外的」の定義にあります。これが私のものです:

例外を発生させたシステムの部分の想定される通常の動作から外れている場合、条件は例外的です。

これにはいくつかの意味があります。

  • 例外はあなたの仮定に依存します。関数が有効なパラメーターが渡されたと想定している場合は、IllegalArgumentException をスローしても問題ありません。ただし、関数のコントラクトで、何らかの方法で入力の入力エラーを修正することが示されている場合、この使用法は「通常」であり、入力エラーで例外をスローするべきではありません。
  • 例外は、サブシステムの階層化に依存します。ネットワークのコメントが解除されている場合、ネットワーク IO 関数は確実に例外を発生させる可能性があります。これは、有効な接続を想定しているためです。ただし、ESB ベースのメッセージ ブローカーは切断された接続を処理することが期待されるため、そのようなネットワーク IO 関数を内部で使用する場合は、エラーを適切にキャッチして処理する必要があります。自明ではない場合、try/catch は事実上、サブシステムが「コンポーネントの 1 つにとって例外的な状態は、実際には正常と見なされているため、処理する必要がある」と言っているのと同等です。
于 2012-03-15T12:09:47.407 に答える
0

KCワリナにはポイントがあります。コードが失敗するケースを特定するのは良いことです (限界まで)

例外をスローするよりも検証する方が良い場合があるというS.Lottに同意します。そうは言っても、OutOfMemory はアプリケーションで期待されるものではありません (大きなメモリを割り当てていて、先に進むためにメモリが必要でない限り)。

アプリケーションのドメインに依存すると思います。

于 2008-10-08T00:37:45.847 に答える
0

クシシュトフ・ツワリナの発言は少し誤解を招くものです。元の文は「例外的な条件」を指していますが、私にとって何が例外的であるかどうかを定義するのは当然のことです。それにもかかわらず、私たちはすべて「開発者」の例外について話していると思うので、メッセージは問題なく通過したと思います。

例外はコミュニケーションに最適ですが、階層設計を少し行えば、特にレイヤー間 (DAO、ビジネスなど) で関心事項を分離するのにも最適です。もちろん、これは、これらの例外を別の方法で処理する場合にのみ役立ちます。

階層の良い例は、Spring のデータ アクセス例外階層です。

于 2008-10-09T14:50:47.077 に答える