例外をどこでキャッチするのが好きですか、そしてその理由は何ですか?
いくつかの一般的なパターンが現れることを期待して、try/catchブロックを配置することが人々に役立つと思う場所を確認することに興味があります。2つの回答例をC++で投稿しますが、どの言語でも問題ありません。
回答ごとに1つの場所と理由をお願いします。ありがとう。
例外をどこでキャッチするのが好きですか、そしてその理由は何ですか?
いくつかの一般的なパターンが現れることを期待して、try/catchブロックを配置することが人々に役立つと思う場所を確認することに興味があります。2つの回答例をC++で投稿しますが、どの言語でも問題ありません。
回答ごとに1つの場所と理由をお願いします。ありがとう。
準備ができておらず、処理できないものは捕まえないでください。
そのため、トップレベルの例外処理を用意して、予期しない例外が発生したときに好きなようにアプリケーションを爆破し、必要な機能を取得するために必要なものだけを (発生している可能性のある場所の近くで) キャッチします。
そして、2 つのことのうちの 1 つだけを行う必要があります。実際に問題を解決/回避するために何かを行うか、キャッチされた例外を として持つより説明的な例外を再スローしますinnerException
。
編集: ブロックが必要でfinally
(たとえば、コードで割り当てたものを解放するため)、ポップアップする可能性のある例外を処理するのに役立つものが何もない場合、同じロジックが適用されます: 単にそれらを処理しないでください。代わりに、 acatch { throw; }
を使用して、すべての例外情報をそのまま維持しながら、例外をより高いレベルに再スローします。(または、単純に catch ブロックを省略します。同じことをすると思いますか?)
私は、対処できる例外のみをキャッチしようとしています。
私はこのようなコードが嫌いです:
String s="12";
Integer i;
try {
i = Integer.parseInt(s);
} catch(ParseException pe) {
System.out.println("hihihihihihihi!!!);
}
私が特に嫌うのは、これが通常行うことは、とにかくスレッドを中止することです。なぜなら、3行後に、i!=nullと見なされるiへのアクセスがあるからです。
次に、スタックトレースを読み取り、ログをスクロールしてスクロールし、他のすべてを崩壊させた最初の重大な間違いを見つけるまでスクロールします。
とにかく、Javaが私に対処できない例外をキャッチするように強制しないことを望みます。しかし、私にできることはこれです:
catch(Exception e) {
throw new RuntimeException(e);
}
そして、関数定義で多くの「スロー」を宣言します。
私はまだ、Eclipseがキャッチされない例外を取得したときに、正しい行でデバッガーを自動的に開く日を夢見ています。その日、私のメソッドは正しい行を開きます。
Smalltalkのような他の言語では、処理できるエラーのみをキャッチします。そして、入力が私の期待を満たさない場合、私は喜んでキャッチされない例外をスローします。
アイデアは、エラーをログに記録したり文書化したりしたくないということです。直して欲しい。
私は常に最後の手段のキャッチとしてmain()にキャッチを入れます:
int main( int argc, char** argv ) {
try {
Application application( argc, argv );
return application.result();
}
catch ( const std::exception& exception ) {
fprintf( stderr, "%s.\n", exception.what() );
}
}
C#とJavaでは、例外をまったくキャッチしないことを好みます。それを避けられない場合は、RunTime例外をすぐに再スローします。
私は常に、必要な最大のスコープを持つ最も貪欲なcatchブロックを使用しますが、常に可能な限り最も具体的な例外タイプを使用します。catchブロックの結果は99.99%のケースで別のスローになるため、完全なメソッドをtryブロック内に保持しようとします。
私は自分の例外処理コードを他のコードから分離しておくのが好きなので、通常は実際のロジックを実行するヘルパー メソッドを作成し、外側のメソッドは例外処理だけを扱います。これにより、コードがきれいになり、読みやすくなるといつも思っていました。
public void stuff() throws MyException
{
try
{
tryStuff();
}
catch (SomeLibraryException e)
{
logger.log("Some message happened", e);
throw new MyException(e);
}
}
public void tryStuff() throws SomeLibraryException
{
// Do things in here that could throw exceptions
}
ビューから発生したイベントを処理するコントローラーのハンドラーをキャッチするのが好きです。例外が安全性の強力な保証を与える場合、これはエラーを報告するのに十分な高レベルであり、ハンドラーは通常アトミックであり、ユーザーが行ったばかりのことに関連しているため、これは有用なキャッチポイントです。どうしたの。
void Controller::on_edit_entity( const Entity& entity ) {
try {
Command::ptr command = new EditEntityCommand( entity );
push_command( command );
}
catch ( const std::exception& exception ) {
fprintf( stderr, "%s.\n", exception.what() );
}
}
(始める前に: 私は Java の専門家です)
私が推奨すること:
handle(Exception e)
最初にそれをチームにリリースし、全員がそれを使用して例外を処理するようにします。例外処理シナリオの変更に基づいて、オーバーロードされた「ハンドル」メソッドを後で追加し続けて、ハンドラーのみを変更する必要があるようにします。Delphi Windows アプリケーションでは、アプリケーションのメイン メッセージ処理ループ(コール スタックの一番下)がメッセージ ボックスを表示して例外を処理します。私の意見では、これは例外を処理するのに最適な場所です。
ユーザーにメッセージ ボックスを表示するという唯一の目的で独自のメソッドで例外をキャッチすることにより、例外が実際に発生し、メソッドが実際に失敗したことをメソッドを呼び出すコードが認識できなくなります。
次の場合にのみ例外を処理します。
2つの場所: