web-dev-qa-db-ja.com

優れたプログラマーが時々静かに例外を飲み込むのはなぜですか?

私はそれが悪いことを知っていますが、優れたプログラマーによって書かれたコードに飲み込まれた例外を見てきました。ですから、この悪い習慣には少なくとも1つの良い点があるのではないかと思います。

言い換えれば、それは悪いことですが、なぜ良いプログラマーは、まれにの場合にそれを使用するのですか?

try
{
    //Some code
}
catch(Exception){}
39
JiBéDoublevé

自分のコードを調べたところ、ログコード内で、ファイルへの書き込みとイベントログへの書き込みに失敗した後、レポートする場所が残っていないため、エラーを飲み込んでしまう場所が見つかりました。それは一例です:他に多くはありません。

44
Steven Sudit

プログラマーはコンパイラーよりも多くの知識を持っていることがあるからです。

例えば。 (ゼロによる除算がエラーと見なされる架空の言語で):

try {
    x = 1 / (a*a + 1);
} catch (DivisionByZeroException ex) {
  // Cannot happen as a*a+1 is always positive
}

一部の言語(Javaなど)では、一部/多く/すべての例外をキャッチする必要があるため、プログラマーがそれが不可能であることを認識しているときに、コンパイラーが文句を言う場合があります。コンパイラをシャットダウンする唯一の方法は、例外を明示的に飲み込むことである場合があります。

コンパイラが文句を言わない言語では、通常、空のキャッチはまったく書き込まれません。

編集:実際には、catchブロックにassert(false)を追加します。理論的に何かが起こらない場合、それが実際に起こるとき、それは非常に深刻な問題です;)

Edit2:Javaは、チェックされた例外をキャッチするだけで済みます。ステートメントを少し言い換えました。

24
Sjoerd

私は、優れたプログラマーはそれを説明せずにそれをしないだろうと主張したいと思います。

try
{
    //Some code
}
catch(Exception e) {
    // Explanation of why the exception is being swallowed.
}

ただし、何らかの理由で、基本のExceptionクラスを黙って飲み込む可能性はほとんどありません。少なくともエラーをログに記録しようと思います。


これは、今日私のプロジェクトで偶然出くわした具体的な例です。これは、ブラウザでサポートされるXMLHttpRequestを取得するJavaScript関数の一部です。

var XMLHttp = null;

if( window.XMLHttpRequest ) {
    try {
        XMLHttp = new XMLHttpRequest();
    } catch(e) {} // we've already checked that this is safe. 
}
else if( window.ActiveXObject ) {
...
}

tryは作成するオブジェクトのタイプをチェックするif...else ifでラップされているため、例外を飲み込んでも安全です。

16
Bill the Lizard

例外を飲み込んだのは2種類しか考えられません。

  1. ファイルまたはデータベース接続を閉じるとき。終了時にエラーが発生した場合、どうすればよいですか?本当になんらかのエラーメッセージを書き出すべきだと思いますが、すでにデータの読み取りに成功しているのであれば、余計なことのようです。また、非常に異なるイベントが発生するようです。

  2. より正当化:内部エラー処理。ログファイルへの書き込みに失敗した場合、エラーを書き込めなかったことを示すエラーをどこに書きますか?状況によっては、画面に書き込もうとすることもできますが、アプリによっては不可能な場合があります。画面のないバックグラウンドジョブ。または、とにかくエラーについて何もできないユーザーを混乱させるだけです。

別のポスターは、例外が不可能であることがわかっている場合、または少なくとも、例外が発生するためには、2つの数値が正しく加算されなかったなど、コンパイラまたはオペレーティング環境に大きな問題が発生する必要があると述べています。例外は意味がありますか?

私は、それが正当であるこれらのまれなケースでは、例外が無関係または不可能である理由を説明するコメントを含める必要があることに心から同意します。しかし、それなら、潜在的に不可解なコードを書くときはいつでも、説明的なコメントを含めるべきだと思います。

補足:プログラマーが「x = x + 1; // xに1を追加する」のようなコメントを日常的に含めるのはなぜですか?コメントなしでそれを考え出すことは決してありませんでしたが、コメントなしで本当に不可解なコードをスローします説明?

私の最初の投稿から4年後の補遺

もちろん、優れたプログラマーでさえ例外を飲み込むことがある本当の理由は次のとおりです。「基本的なロジックを機能させようとしています。この例外が発生した場合の対処方法がわかりません。今はそれをいじりたくありません。 、通常のロジックフローに問題がありますが、後で戻ります。」そして、彼らはそれに戻るのを忘れます。

ところで、私が一般的にかなり優れたプログラマーだと思う何人かの人々から聞いた悪い理由は、「ユーザーに不可解なエラーメッセージを表示したくない。それは彼らを混乱させるだけだ。エラーを黙って飲み込むほうがよい。 「」これは悪い理由です。(a)ログファイルに何かを書き込むことができるからです。そして(b)不可解なエラーメッセージは、操作が成功しなかったのに成功したという印象をユーザーに与えるよりも本当に悪いですか?これで、顧客は、注文が実際には処理されていないときに処理されていると考えたり、救急車が派遣されて、苦しんで叫んでいるが実際にはメッセージが届かなかった子供を支援していると考えたりします。 、フォーラムへの当たり障りのない投稿が行われなかったなど、私は一致するのではなく、少なくとも何かがうまくいかなかったという考えを私に与える不可解なメッセージを受け取ります。気になる場合は、もう一度試すか、誰かに電話して、「更新が完了していません」。

11
Jay

良いプログラマーでさえ間違いを犯すことがあるからです。

それまたは優れたプログラマーに対するあなたの意見は、一部の人と同じではありません(優れたプログラマーは、情報を使って何かが行われるのではなく、例外が飲み込まれた理由について何らかの理由を残していたためです)。

7
Justin Niessner

プレゼンテーションのために何かを終了する必要があるため、上司は明日自発的に行い、プログラムがクラッシュしたり、厄介なエラーメッセージを表示したりすることほど悪いことはありませんが、何かが機能していないときはいつでもそれについて「話し合う」ことができます。

もちろん、プレゼンテーションの後、これらの「迅速に修正された」部分を改善する人は誰もいません。 ;-)

6
herzmeister

はい、元の例外をマスクしないように、例外クリーンアップコードで頻繁に使用しています。

たとえば、catchハンドラーがトランザクションをロールバックし、例外を再スローする前に接続を閉じようとしている場合、ロールバック/クローズ自体が失敗する可能性があるいくつかの理由が考えられます(元の例外)。したがって、空のcatchハンドラーを使用してtryブロックでクリーンをラップすることをお勧めします。基本的には、「クリーンアップで問題が発生した場合、報告する問題が大きいため、問題はありません」と言います。

5
Mike Mooney

Javaのチェックされた例外が原因だと思います。人々はどこでも例外処理コードが必要だと考える傾向があるので、私は個人的に彼らを嫌います。コードの99%のIMOは、例外をスタックにスローし、処理しないようにする必要があります。作成された新しいメソッドのデフォルトの署名に「throwsException」が含まれていれば、必要がない限り例外を処理する必要がないので嬉しいです。

IMOでは、次の2つの場所でのみ例外処理が必要です。1。入力ストリームのクローズ、データベース接続、ファイルの削除などのリソースのクリーンアップ。 2.例外をキャッチし、ログに記録するか、ユーザーに表示するスタックの最上部。

Thread.sleep()からのInterruptedExceptionの処理など、キャッチで実際に何もする必要がない場所があります。少なくとも、何も起こしたくないことを明確にするためのコメントが必要です。そこ。

5
Sarel Botha

私はこの古いスレッドに出くわし、良いコードが単に例外を飲み込む(コメントの有無にかかわらず)唯一の正当な理由がわからないことに驚きました。

ライブラリと制御できないコードを使用してコードを作成する場合、メソッドを呼び出して、そこにある場合とない場合がある値を取得したり、の特定の時点で許可されない可能性のある操作を実行したりする必要がある場合がよくあります。時間。呼び出しているメソッドが、制御フローの代替を提供する代わりに有効な結果を返すことができない場合に例外をスローすると、値が使用できないか、操作を実行できないことを示すシグナルとして例外を飲み込むことを余儀なくされます。

優れたプログラマーは、エラーとしてユーザーにバブルする可能性のある実際の障害シナリオを除いて、制御フローを駆動するために例外処理を使用しないようにあらゆる努力をします。ただし、優れたプログラマーは、効率を上げるためにライブラリとフレームワークを広範囲に再利用し、ライブラリを書き直してより良い代替手段(TryGetValueパターンなど)を提供することが常に選択肢であるとは限らないことを理解しています。

2
Jamie Thomas

これは、失敗したにもかかわらずプログラムを続行したいコードがいくつかある場合に実行しました。たとえば、オプションのログファイルを開いたのですが、それが機能しなかった理由に関係なく、プログラムの実行を続行したいと思います。

それでも、メモリ不足の例外など、無視してもまったく意味がない例外が発生する可能性があるため、これは適切なコードではありません。それを実行したとしても、それでも最善のアイデアではなく、公衆。 (おっと...)

コンパイラをシャットダウンするためだけにデータなどを変換するために一度実行することを目的としたプログラムでこれを実行しました。ただし、これは、どのような形式の本番コードともまったく異なる状況です。

基本的に、怠惰以外にこれを行う正当な理由はありません。

1
jcoder

例外を効果的に処理できない場合、アプリケーションの通常の動作に影響を与えない場合、および/または既知であるが全体的な影響がほとんどない一時的な状態を表す場合に行います。

簡単な例はロギングです。一部のログ情報がバッキングストアに保存されないという理由だけで、アプリを爆破する必要はありません。

別の例として、次のような状況を処理する別の手段がある場合があります。

private Boolean SomeMethod() {
   Boolean isSuccessful = false;
   try {
      // call API function that throws one of several exceptions on failure.
      isSuccessful = true;
   } catch(Exception) { }

   return isSuccessful;
}

上記の例では、フォールバック位置がない場合がありますが、フィルター処理は望ましくありません。これは、tryブロックの最後のステップとして戻り値が成功ステータスにのみ設定されるSHORTメソッドでは問題ありません。

残念ながら、結果にエラーコードや誤った条件を返すだけでなく、例外をスローする呼び出しが多数あります。また、ドキュメントが示唆しているよりも多くの例外をスローする呼び出しも見ました。これが、私がそれらの周りにキャッチを置く理由の1つです。

1
NotMe

優れたプログラマーであると主張することなく、少なくとも私が時々捕まえて無視する理由を説明することができます。私が取り組んでいるものは、コンパイルするために例外を処理しなければならない場合がありますが、実際に例外を処理するのに適切な場所ではありません。たとえば、私は最近、タスクの1つとして大量のXMLを解析するプログラムで作業していました。実際のXMLパーサーがファイルを開いたため、例外が生成されました。ただし、XMLパーサーは、ファイルの選択が不適切であることをユーザーに通知するダイアログを生成するのに最適な場所ではありませんでした。例外を適切な場所にスローしてそこで処理することで脇道に追いやられるのではなく、私は黙って例外をキャッチし、コメントとTODO(私のIDEは私のために追跡します)を残しました)。実際に例外を処理せずにコンパイルしてテストします。TODOの処理をすぐに忘れてしまい、飲み込まれた例外がしばらく続くことがあります。

私はこれが最良のプログラミング手法ではないことを知っています、そして私は確かに専門のプログラマーではありません、しかしこれは誰かがこれをしたいと思う理由の例だと思います。

1
Zoe

少なくとも出力ウィンドウに書き込みます

try
{ }
catch (exception ex)
{
System.Diagnostics.Debug.Writeline(" exception in method so and so : " ex.message);
}
0
fishhead

進行状況制御の更新を実行する場合はどうですか?コントロールの描画ルーチンで使用される状態変数を更新したので、次にコントロールが描画されるときに、適切な状態が表示されます。次に、以下を実行します。

 Try 
 MyControl.BeginInvoke(MyControlUpdateDelegate); 
 Exを例外としてキャッチ
 End Try 

コントロールがまだ存在する場合は、更新されます。処分されても更新されるかどうかは気になりません。コントロールが破棄されていないが、他の理由で更新できない場合でも、とにかくそれについて賢明なことは何もできない傾向があるので、更新されるかどうかは気にしません。

「IfNotMyControl.IsDisposed Then ...」を追加することもできますが、それは一般的なケースに作業を追加するだけであり、BeginInvoke中にコントロールが破棄された場合に例外が発生するのを防ぐことはできません。

0
supercat

私が作成するアプリケーションの性質上、キャッチしたほとんどすべての例外をファイルに記録する必要があります。

例外は、いかなる種類の再スロー、ロギング、または例外が黙って食べられた理由を説明するコメントさえもなしに食べてはなりません。私の初期の頃は、自分だけがコードに取り組んでいることを知っていれば、例外をよく食べていました。もちろん、コードを再検討するときは、その例外が実際に何を意味していたかを忘れてしまい、もう一度理解するためにすべてを再テストする必要がありました。

0
ravibhagw

ランタイムエラーには例外を使用します。ユーザーや、時には要件など、問題が発生したときに発生することが原因です。また、ユーザーにエラーを表示したい場合は、例外を発生させる可能性があります。例えば:-

  1. ソフトウェアの実行中は、要件が誤っている可能性があり、プログラム自体で解決できます。そのため、このような場合、プログラマーはtryステートメントを使用することを選択し、ソフトウェアでは解決できないハードウェア要件が存在する可能性があります。そのような場合、プログラマーは例外を発生させるパスを選択してユーザーに警告します。

また、状況に応じて、例外を発生させたり、例外を処理したりするパスを選択する場合が多くあります。

0
Anu