読者です 読者をやめる 読者になる 読者になる

【Effective Java】項目63:詳細メッセージにエラー記録情報を含める

Java Effective Java

システムがキャッチされない例外で終了すると次の情報が出力されます。

最後の「例外の詳細メッセージ」はエラーの原因を調査するための唯一の手がかりであることが多いです。 そのため、例外の詳細メッセージにはエラー時の記録情報を必ず含めるべきです。

たとえば配列の範囲外にアクセスしているという IndexOutOfBoundsException 例外なら詳細メッセージには次の値を含んでいるべきです。

  • 実際のインデックス
  • 下限範囲
  • 上限範囲

このとき、不必要なメッセージを含める必要はありません。

例外のメッセージとエンドユーザーに表示するメッセージは異なります。 エラーを解析するプログラマやサポートエンジニアにとって分かりやすい、端的なメッセージにするべきです。

コンストラクタイディオム

例外に必要なエラー情報を必ず含めることを保証する方法の一つは、コンストラクタでその情報を要求することです。

例えば、IndexOutOfBoundsException をこの手法で実装すると次のようになります。

/**
 * IndexOutOfBoundsException を生成する
 *
 * @param lowerBound 最も小さな正当インデックス値
 * @param upperBound 最も大きな正当インデックス値に 1 を足した値
 * @param index 実際のインデックス値
 */
public IndexOutOfBoundsExcetion(int lowerBound, int upperBound, int index) {
    super("Lower bound: " + lowerBound + 
        ", Upper Bound: " + upperBound + 
        ", Index: " + index);
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.index = index;
}

この方法は Java ライブラリで使われていませんが、かなり有用なイディオムです。

このイディオムを利用すれば、プログラマがエラーの記録をスキップすることはできません。 また、例外スローのたびにメッセージを生成する処理を書く必要もありません。

加えて、これらの情報へのアクセッサを提供することが適切かもしれません 特にチェックされる例外では、エラーから回復する時に有用な情報かもしれません。この場合は積極的にアクセッサを提供するべきです。

チェックされない例外でも、toString() 文字列をパースされてしまうことを防ぐためアクセッサを提供してもいいかもしれません。