3

ライブラリから例外をバブルアップする最良の方法は何ですか? インターフェイスを実装するとき、実装の詳細に関する例外で呼び出し元にバグを報告するのは良い習慣ですか、それとも悪い習慣ですか? すべての実装エラーが発信者から隠されている次の実装があります。私には、関心の分離を実装する最もクリーンな方法のように見えます。しかし、手つかずの例外をバブルアップする必要があることをどこでも読みました。

public class OneException : Exception
{
    public OneException()
    {
    }

    public OneException(string message): base(message)
    {
    }

    public OneException(string message, Exception innerException)
      : base(message, innerException)
    {
    }
}

そして私のライブラリの実装:

public class MyLib : IMyLib
{
    public int Divide(int a, int b)
    {
        try
        {
            if (b == 1) throw new OneException();
            return a / b;
        }
        catch (OneException e)
        {
            throw new ApplicationException("Please do not divide by 1", e);
        }
        catch (Exception e) // divide by zero and others
        {
            throw new ApplicationException("Oops", e);
        }
    }
}
4

7 に答える 7

3

Single Responsibility Principle に従って、ライブラリが行うべきことを (可能であれば) 処理する必要があります。それ以外の場合は、呼び出し元に対処させる必要があります。

あなたの例では、ゼロ除算の例外を正しくスローします。これを処理することは、ライブラリの責任ではありません (「安全な」除算方法として宣伝していない限り)。エラーはクライアント入力が正しくないために発生したため、それを処理するのはクライアントである必要があります。

ただし、OneException は例外としてスローされることはありません。クライアントが 1 で割り切れないのはなぜですか? 確かに害はありません。これはおそらく不自然な例ですが、内部で解決できない問題が実際にない限り、例外をスローしないでください。誰かが 1 で割りたいのなら、どうして許してはいけないのでしょうか?

優れた例外処理は、ロジックのエラーではなく、入力やシステム障害に関する問題をクライアントに通知します。

于 2012-06-13T07:49:07.913 に答える
2

例外バブリングの適切な戦略の選択は、次の 2 つの主な要因によって異なります。

  1. 例外コンテキストに関する詳細を可能な限り呼び出し元に提供しますか?
  2. 重要な例外データを呼び出し元から隠したいですか?

例外コンテキストに関する詳細を提供したい場合は、例外をより具体的な例外にラップすることをお勧めします。ここでの最も明白な例は、ビジネスの例外です。

機密データを例外から隠したい場合は、例外を置き換えることを検討してください。このアプローチは、発信側が信頼されていない場合に、サービスで一般的に使用されます。

注:通常のプログラム フローの一部でない限り、例外を「飲み込む」べきではありません。

于 2012-06-13T19:00:54.883 に答える
1

どちらの例外もシステムによってカバーされています。b = 1 の場合は ArgumentOurOfRange 例外を使用し、b = 0 の場合は DivideByZeroException を使用します。したがって、非常に単純なサンプル ライブラリの場合、追加の例外を作成する必要はありません (これは良い方法ではありません)。すぐに例外をスローするかどうかは、要件の問題です。ほとんどの場合 (グッド プラクティス)、呼び出し元が try/catch(/finally) を使用して処理できる例外をスローします。

于 2012-06-13T07:46:26.310 に答える
1

原則として、処理できる例外のみを処理してください。

ライブラリの実装では、さまざまな例外をキャッチし、OneExceptionそれExceptionを として再スローしApplicationExceptionます。元のエラーの意味を完全に隠しているため、これは悪い習慣だと思います。

ライブラリの Divide() メソッドを使用するクライアント コードは、発生した唯一の例外が原因の手がかりApplicationExceptionを与えないジェネリックである場合、正確に何が起こったのかをどのように知る必要がありますか?

ここで行うことは、例外をスローし、同じメソッド内でキャッチして、別の例外を再スローすることです。

例外をクライアント コードにバブル アップさせて、クライアントが処理方法を自分で決定できるようにします

于 2012-06-13T07:36:59.090 に答える
1

場合によります。何らかのビジネス ルールのために例外を処理し、カスタマイズされた例外を発生させたい場合は、必ず例外を処理し、それをログに記録するか、新しいカスタマイズされた例外を発生させますdivide by 1

もう 1 つの例として、テーブルにデータを入力していて get Primary key 制約例外が発生した場合、例外をキャッチしてライブラリの仕様に従って独自のカスタマイズされた例外を発生させるか、例外をそのままにしておくことができます。呼び出しコードで処理されます。

内部エラー/例外ログを維持している場合は、ライブラリで例外を処理すると役立つ場合があります。例外をログに記録し、それをスローして、呼び出し元のコードにバブルアップできるようにすることができます。ただし、カスタマイズされた例外をログに記録したり発生させたりしていない場合は、呼び出し元のコードで処理できるように、例外をそのままにしておくことをお勧めします

于 2012-06-13T07:37:31.523 に答える
1

例外をログに記録してみてください。これは常に良い習慣です。このようにして、クライアントは何がうまくいかなかったのかを実際に知ることができます。

于 2012-06-13T07:39:20.823 に答える
1

次の質問を自問してください。

  • 開発者として、消費者 (呼び出し元) にライブラリについて何を知ってもらいたいですか?

  • 消費者として、エラーが発生した場合に何を望みますか?

標準の .Net 例外が目的に不十分な場合にのみ、独自のタイプの例外の公開を開始する必要があります。この例として、COM 関連のエラーがあります。特別な番号が埋め込まれた COMExceptions のスローを回避する方法として、特定のエラー条件に対してカスタム例外を作成することができます。

あなたの例では時間の無駄だとOneException思います-なぜ標準例外としてスロー、キャッチ、ラップ、再スローするのですか? そもそも投げてみませんApplicationExceptionか?これは、例外を使用してプログラム フローを制御することとほぼ同じであり、これはアンチパターンです。

于 2012-06-13T07:39:58.043 に答える