5

次のコードがあるとします。

void foo() {
    /* ... */
    try {
        bar(param1);
    } catch (MyException e) {
        /* ??? */
    }
}

void bar(Object param1) throws MyException {
    /* ... */
    try {
       baz(param2);
    } catch (MyException e) {
        /* ??? */
    }
}

void baz(Object param2) throws MyException {
    /* ... */
    if (itsAllATerribleMistakeOhNo) {
        /* ??? */
        throw new MyException("oops, error.");
    }
}

エラーをどこでどのようにログに記録する必要があるのか​​疑問に思っています。

  • 以下のbaz()でエラーが発生した場合、どの操作が失敗したかを正確に把握しており、その事実をログに記録できます。
  • 一番上には、最も一般的なコンテキストがあります(たとえば、処理中にエラーが発生した接続のIPは何ですか)。
  • 途中で、上部にも下部にもわからないコンテキストがあるかもしれません。

もう1つの厄介な問題は、下のエラーが上から見たときに実際にはエラーと見なされない可能性があることです(たとえば、データベースで何かを検索すると失敗します。確信が持てなかった可能性があります)。そのため、logger.WARN()の代わりに選択する可能性がありますlogger.ERROR()

したがって、上記では3つの場所(下、上、および途中)について説明しましたが、ログを記録する場所だけでなく、何をスローするかという問題でもあります。中央のすべてのレベルで、2x2のオプションがあります。

  • メッセージをログに記録する/ログに記録しない
  • 元の例外をスローする/追加されたメッセージを含む新しい例外で例外をラップします。

これらの複雑な選択に関するベストプラクティス、またはいくつかの一般的な知恵は何ですか?

注:エラー処理/例外の使用全般については質問していません。上記のジレンマについてだけ質問しています。

4

4 に答える 4

2

私が従う傾向があるいくつかの提案:

いくつかのベストプラクティスへのリンク

1)発生した例外をトレースします。クラスまたはAPIが例外が発生するコンテキストを知っている場合に例外が発生するポイントとして、適切なログをトレースして提供する方が適切です。ただし、APIが正確なコンテキストを処理またはコメントできない場合、APIはイベントをログに記録して、呼び出し元に残してはなりません。

2)例外のラップ:スローできる例外が多数あり、すべての例外が同様のグループ(SQLException)を形成し、単一の例外を提供し、必要に応じて情報を抽出できる場合。そうしないと、呼び出し元が処理する必要のある例外が急増することになります。

3)例外の再スロー: APIが例外をログに記録し、ユーザーがその例外に対して何らかのアクションを実行できる場合は、エラー状態が発生したことをユーザーに通知するために、例外を再スローする必要があります。

4)例外の適切な原因:例外メッセージは、呼び出し元が理解するには技術的すぎてはなりません。メッセージ自体が、例外の根本的な理由を理解するようにユーザーをガイドする必要があります。

更新: Javaでの例外管理

于 2013-03-04T08:23:34.247 に答える
2

ロギングに関しては、すべてのロギングをアプリケーション境界の一番上に保持することを好みます。通常、私はインターセプターまたはフィルターを使用して、すべてのロギングを一般的な方法で処理します。この概念により、すべてが1回だけログに記録されることを保証できます。

この場合、foo()メソッド内、またはアプリケーションへのエントリポイントが何であれ、ログに記録します(IPアドレスについて言及しましたが、サーブレットコンテナまたはアプリケーションサーバーについて話していると思います)。

それよりも、フィルター/インターセプターで独自の例外をキャッチし、必要に応じてログに記録します。を追加しcatch throwableて、コードで処理しなかった他のすべての例外をキャッチし、それらをエラーとしてログに記録します。これは、明らかにスタックトレースのさらに下の何かを見逃したためです。

この概念には、事前の計画が必要です。ApplicationExceptionおそらく、エラーメッセージ(文字列)といくつかの重大度レベル(おそらく列挙型)を格納する独自のものを使用するでしょう。実際のログ記録を行うときに正しいログレベルを選択するには、これが必要です。

これはすべての場合にうまく機能し、すべてのロギングが1回だけ行われるという利点があります。ただし、コードにログインする必要がある場合が1つあります。コードのどこかでエラーに完全に対処できる場合(つまり、例外が発生し、(再)スローせずに作業を続行できるようにすることができます。例外)。例外をスローしていないため、それ以外の場合は何もログに記録されません。

要約すると:

  • 一般的な方法で、できればインターセプターまたはフィルターを使用して、最上部の位置にログを記録します。
  • 例外を独自のApplicationExceptions内にラップし、アプリケーションにログインするための重大度とその他の重要事項を追加します。
于 2013-03-04T09:27:46.360 に答える
1

コードで例外をスローするとき、通常は何もログに記録しません。例外は十分な情報です。これに対する唯一の例外は、システムの境界にいるとき、つまり、例外がシステムの境界を離れるとき、他のシステムがエラーをどのように処理するかわからないため、ログに記録することです。

例外を処理するときは、アクティブに処理するときにログに記録します。つまり、catch句を使用しているときに、例外を再スローするだけではありません。通常、これはかなり上にありますが、これは状況によって異なります。

于 2013-03-04T08:22:07.500 に答える
1

テスト段階で例外をスローするときは、次のことを覚えておく必要があります。

  • 例外メッセージはできるだけ明確にしてください。スタックトレースは、最良の場合は混乱を招く可能性があるため、少なくとも、読んでいる内容が理解できるものであることを確認してください。
  • 例外がイベントに関連していることを確認してください。ユーザーが間違った値を入力し、NullPointerExceptionをスローすると、コードは非論理的であり、その値を失います。
  • イベントに関するできるだけ多くの情報が含まれていることを確認してください。つまり、メッセージを適切に保ちます。データベース呼び出しが失敗した場合は、データベースへの接続文字列を出力し、SQLクエリを試行します。現在使用されているすべての変数の状態は必要ありません。
  • ワッフルしないでください。マトリックスにハッキングしているように見せるために、専門用語を入力したくなります。それはストレスの多い状況であなたを助けません、そしてそれは確かにあなたのコードを使用している他の誰かを助けません。単純な英語の単語が常に望ましいです。
  • 最後に、例外を決して無視しないでください。常に例外を処理し、上記のルールに従って何らかの方法で詳細を出力していることを確認してください。
于 2013-03-04T08:22:11.530 に答える