web-dev-qa-db-ja.com

エラー処理を実装する方法

私は数年プロレベルでプログラミングしてきましたが、まだエラー処理を完全には理解していません。私のアプリケーションは正常に動作しますが、エラー処理は専門家レベルでは実装されておらず、さまざまな手法を組み合わせたものです。

私のエラー処理の背後にある構造はありません。それが専門家レベルでどのように実装されているかを学び、理解したいと思います。これは、私が知識を欠いている分野の1つです。

ロジックフローでチェックするために、いつ例外を使用し、いつ成功ステータスを返す必要がありますか?例外とステータスを返すことを混在させても大丈夫ですか?

主にC#でコーディングします。

13
James Jeffery
  1. 例外的なもの、つまり、頻繁に遭遇することを合理的に期待できないもの、何かがうまくいかないことを示すものには例外を使用します。たとえば、ネットワークがダウンしている場合、それはWebサーバーにとって例外的なことです。データベースが利用できない場合、それは何かが間違っていることを意味します。構成ファイルが欠落している場合は、おそらくユーザーがそれをめちゃくちゃにしたことを意味します。

  2. 例外を使用して不正なコードを処理しないでください。コードが正しいかどうかを確認するには、アサーションを使用するか、.NET Framework 4以降ではコードコントラクト(アサーションに代わるものであり、特に重要な機能を備えています)を使用する必要があります。

  3. 例外的なケースでは例外を使用しないでください。ユーザーが番号の入力を求められたときに「犬」と入力したという事実は、例外に値するほど例外的ではありません。

  4. 例外のタイプを選択するときは注意してください。必要に応じて独自のタイプを作成します。親を捕まえると子供も捕まえられることを念頭に置いて、慎重に継承を選択しました。決して_throw Exception_しないでください。

  5. エラーには戻りコードを使用しないでください。エラーコードは簡単にマスクされ、無視され、忘れられます。エラーがある場合は、エラーを処理するか、上位スタックに伝達します。

  6. メソッドがエラーを返すことが予想され、エラーが例外的でない場合は、列挙型を使用し、エラー番号は決して使用しないでください。例:

    _// Note that the operation fails pretty often, since it deals with the servers which are
    // frequently unavailable, and the ones which send garbage instead of the actual data.
    private LoadOperationResult LoadProductsFromWeb()
    {
        ...
    }
    _

    _LoadOperationResult.ServerUnavailable_、_LoadOperationResult.ParsingError_などの意味は、たとえば、コード12はサーバーがダウンしていること、コード13はデータを解析できないことを覚えていることよりもはるかに明確です。

  7. エラーコードは、特定のドメインで作業するすべての開発者が知っている一般的なエラーコードを参照するときに使用します。たとえば、HTTP 404 Not FoundまたはHTTP 500内部サーバーエラーの列挙値を再発明しないでください。

  8. ブール値に注意してください。遅かれ早かれ、特定のメソッドが成功したか失敗したかだけでなく、その理由も知りたいでしょう。そのためには、例外と列挙型の方がはるかに強力です。

  9. すべての例外をキャッチしないでください(スタックの一番上にいる場合を除きます)。例外をキャッチした場合、それを処理する準備ができているはずです。すべてをキャッチすると、コードが正しく実行されていても気にしないことがわかります。これで「今すぐ検索したくないのですが、修正方法」は解決するかもしれませんが、遅かれ早かれあなたを傷つけるでしょう。

  10. C#では、次のような例外を再スローしないでください。

    _catch (SomeException ex)
    {
        ...
        throw ex;
    }
    _

    スタックを壊しているからです。代わりにこれを行ってください:

    _catch (SomeException)
    {
        ...
        throw;
    }
    _
  11. 例外メッセージを書くときは努力してください。 throw Exception("wrong data")またはthrow Exception("shouldn't call this method in this context")のようなものを見たことがありますか。 6か月後の自分を含む他の開発者は、どのデータが間違っているのか、なぜ、なぜコンテキスト内でメソッドを呼び出すべきではないのか、またどのコンテキストを正確に呼び出すべきではないのかわからないでしょう。

  12. ユーザーに例外メッセージを表示しません。それらは一般の人々には期待されておらず、開発者自身にとっても読みにくいものであることがよくあります。

  13. 例外メッセージをローカライズしないでください。ローカライズされたメッセージをドキュメントで検索するのは、骨の折れることで無意味です。すべてのメッセージは英語と英語のみである必要があります。

  14. 例外とエラーだけに焦点を当てないでください。ログも非常に重要です。

  15. .NETでは、メソッドのXMLドキュメントに例外を含めることを忘れないでください。

    _/// <exception cref="MyException">Description of the exception</exception>
    _

    XMLドキュメントに例外を含めると、ライブラリを使用している人にとって非常に簡単になります。メソッドによってスローされる可能性のある例外とその理由を推測することほど厄介なことはありません。

    この意味で、 Java例外処理 は、より厳密で優れたアプローチを提供します。呼び出されたメソッドによってスローされる可能性のある例外に対処するか、処理しない例外をスローできることを独自のメソッドで宣言して、特に透過的なものにする必要があります。


beingこれが言われているように、言語が例外をチェックしたりチェックを外したりすると、Java例外とエラーの区別はかなり役に立たず混乱します。幸い、.NET Frameworkには例外しかなく、エラーはありません。

25

MainMaのリストは非常に完全だと思います。私は自分のいくつかを追加します:

  1. Eric Lippertが例外をどのように分類するかについて 記事 を読んでください。特に重要なのは、実際にはコード内のバグである例外をキャッチしないという点です。代わりにコードを修正してください!
  2. 例外が発生する可能性があることを知っていて、それに対して何かを行うことができる場合は、それを処理しますが、試行の範囲を制限して、予想している特定の例外をキャッチします。つまり、これを行わないでください。

public void Foo() {
    try {
        //get input from use
        //do calculations
        //open file
    }
    catch (Exception ex) {
       //handle exception
    }
}

代わりにこれを行います:

public void Foo() {
    //get input from use
    //do calculations
    try {
        //open file
    }
    catch (FileOpenException ex) {
       //handle exception
    }
}
  • 制御フローに例外を使用しないでください。たとえば、ルックアップダイアログでClientNotFoundExceptionをスローしないでください(この場合、クライアントが見つからないことは例外ではありません)。これが発生すると、呼び出しコードに「結果が見つかりません」というメッセージが表示されることを期待します。

  • 例外を飲み込まないでください!

  • 例外を本当に処理するということは、3つのことしか意味しないことに注意してください。

    1. 操作を再試行してください。問題が一時的な場合にのみ有効です。
    2. 別の方法を試してください。
    3. 問題について誰かに通知します。通知が実行可能な場合、つまりユーザーがそれに対して何かを実行できる場合にのみ有効です。

    これらのオプションのいずれも適用されない場合は、おそらくその例外をキャッチしないでください。ただし、ログに記録してから、操作をキャンセルするかシャットダウンする必要があります。もちろん、これは正確性と堅牢性に関する要件が何であるかに依存します。

1
Mike