2011-07-23 10 views
1

私は今まで書いてきたすべてのバグのコードに疲れているので、例外を扱う正しいアプローチを理解する必要があるようです。私は投げられる/投げられるべきものは何ですか?

のは、次の例について考えてみましょう:私はREADDATA()が何らかの理由で失敗した場合にキャッチすることを期待することができます例外は何ですか、私はあるIDataSourceを実装するクラスのオブジェクトを使用している場合は

interface IDataSource 
{ 
    string ReadData(int offset); 
} 

class FileDataSource : IDataSource {...} 
class DatabaseDataSource : IDataSource {...} 

を?

FileDataSourceは、ファイルが存在しないか、ファイルがオフセットよりも小さいために失敗することがあります。 DatabaseDataSourceは、データベースに接続できないか、そのデータベースに必要なテーブルがないため、失敗する可能性があります。

私はこれを実行します。

var data = dataSource.ReadData(10); 

私は何をキャッチする必要がありますか?反対側から、新しいクラスFakeDataSourceを実装している場合、何か悪いことが起きたらどうすればいいですか?

私はDatabaseDataSourceからFileDataSourceまたはSqlExceptionからFileNotFoundExceptionを投げるとき、私は実装の詳細を知っているので、それは、カプセル化違反を意味することを感じています。

IDataSourceによってスローされたすべての例外をこのインタフェースにバインドする必要がありますか?つまり、新しい抽象を定義するときに、関連する例外も定義する必要があります。このように:誰かがIDataSourceを実装することを決定したときに

interface IDataSource { ... }  
abstract class DataSourceException : Exception { ... } 

そう、彼は唯一のDataSourceException秒をスローする必要があります。あれは正しいですか? offsetの値が間違っているのはなぜですかDataSourceExceptionまたは標準(.NET)ArgumentOutOfRangeExceptionはOKですか?

エラー処理についての記事へのリンクもありがたいと思います。

答えて

3

処理できる例外のみをキャッチする必要があります。 IDataSourceがFileNotFoundExceptionまたはSqlExceptionをスローし、それを処理できない場合は、それをキャッチしないでください。

例外をスローするときは、その問題を最もよく説明する例外の型をスローする必要があります。 three things that you want to know from a thrown exceptionがあります。

  • 何が問題になりましたか?
  • どこが間違っていましたか?
  • なぜそれが間違っていましたか?例外スタックトレースで答えているスロー 例外の種類、によって回答されているものの例外を効果的に使用されている

、および はなぜ例外メッセージで応答します。あなたの例外を見つけるならば、 は3つの質問すべてに答えていない、彼らは効果的に使用されている ではない可能性があります。プログラムをデバッグするときに、例外を最大限に活用するために、3つのルールが役立ちます。これらのルールは、具体的には、 が早く投げられ、遅く捕らえられます。

ほとんどの場合、独自に作成するのではなく、一般的に定義されている例外を使用します。人々は彼らに精通し、追加の説明なしに彼らが何を意味するのか理解するでしょう。ただし、独自の例外タイプを作成すると、特定のモジュールの詳細をカプセル化することが望ましい場合に役立ちます。このアプローチをとるときは、元の例外をモジュールの例外内にラップして、情報が再スローされたときに情報が失われないようにします。

1

例外をスローするための具体的なルールはないと私は思います。おそらくそれはプログラマにとって非常に主観的な選択肢です。つまり、あなたは別のオプションを持つことができます。あなたが言及したように、ビルドされた例外をスローするか、グループに属するクラスからカスタム例外をスローすることができます。

このシナリオでは、どこから来ているのか正確に知っているので、独自のカスタム例外をスローするほうがよいでしょう。 (これをインターフェースモデルで強制する実際の方法はありません)また、例外が起きたときに何をしているのかによって異なります。これには厳密かつ迅速なルールはありませんが、例外を正常に処理する必要があります。私はバグのコードを書いているとは思わない。例外は多くの理由により発生します。データベース接続の失敗はあなたの手元にありません。ほとんどの場合、データベースが停止しているときにアプリケーションが機能しないことがあります。あなたが例外をキャッチし、ログし、必要なグループに通知し、うまく失敗する以外のことはあまりありません。悪いアプリケーションは、サーバー情報をユーザーに表示し、誰にも通知しないので、顧客はそれを修正するために呼び出しを行う必要があります。

PS:filedatasource(またはsqldsの対応するもの)から見つからないファイルがカプセル化に違反しているとは思えません。そのクラスは、特定の目的のクラスであるため、実装の詳細を知っているはずです。

2

例外は、ライブラリ/アプリケーションが要求されたことを行うことができず、回復する必要があるかどうかを判断するのに役立つ例外的な条件でのみスローする必要があります。

あなたの例外は、起こったことを正確に特定する必要があります。それらは、問題が何であるかを正確に示すメッセージで、トップレベルの問題が何であるかを示すために十分に一般的でなければなりません。さまざまなタイプの操作に基づいて例外カテゴリを分類します。

接続に問題がある場合は、ConnectionExceptionをスローし、そのメッセージを使用して例外がスローされる理由を指定します。データベースに接続できない場合は、その旨を示すメッセージが表示されます。不正なユーザー名ですか?パスワードが間違っていますか?発信者に知らせる。等々。

クエリに問題がある場合、クエリしようとしているテーブルが存在しない場合のように、QueryExceptionをスローします。

DataSource実装のすべての例外をDataSourceExceptionに限定することは、すべての例外をException型として投げることとほぼ同じくらい悪いものです。あなたはそうしないだろうか?

また、DataSourceExceptionで例外をラップすることもありません。私はこれが必要以上にあなたの実装にはるかに複雑なものを加えると思います。

new DataSourceException(new ArgumentException("Range is invalid"), "Range is invalid"); 

またはこの:それはまた、あなたがこのようなコードの束を持っているだろうと読みやすさがもう少し複雑にします

消費クラスのすべてのためのその後
try { 
    ... 
} catch (Exception e) { 
    throw new DataSourceException(e, e.Message); 
} 

あなたの実装では、例外をキャッチする必要がありますし、内部の例外を調べて、それが正常に処理したいものかどうかを確認してください。

それは意味がありますか?

2

なぜあなたはそのレベルで何かをキャッチしたいですか?

例外を処理する方法を知っているのは1つの理由だけです。

ログに記録したい場合はキャッチすることができますが、その場合は例外を再現する必要があります。しかし、これは場所全体に同じログラインを繰り返すことを意味します - より良い方法は、メインループに一度ログを記録することです。例外にはスタックトレースが含まれています。

DataSourceExceptionをキャッチして再利用するのが一般的なJavaソリューションです.1つ目の目的は、Javaコンパイラを満たすことだけです。結局のところ、FileNotFoundException、またはDataSourceExceptionの原因を処理する場合に、さらに便利なのは何ですか?

私の答えは:例外を処理する方法がわからない限り、キャッチしないでください!

0

何が起こったのか、何故操作が失敗したのかを記述してください。あなたは実際に処理できる例外を期待するだけで、例外をキャッチすることはありません。

関連する問題