22
Effective Java 輪読会 第8(項目63652014/2/26 開発部 野口

Effective Java 輪読会 項目63-65

Embed Size (px)

Citation preview

Page 1: Effective Java 輪読会 項目63-65

Effective Java 輪読会第8回(項目63~65)

2014/2/26

開発部野口

Page 2: Effective Java 輪読会 項目63-65

項目63

詳細メッセージにエラー記録情報を含める

Page 3: Effective Java 輪読会 項目63-65

例外の文字列表現は、

後の分析のためにエラーを記録する プログラムがキャッチされなかった例外により失敗した場合は、システムは自動的にその例外のスタックトレースを表示する

スタックトレースには、その例外の toStringメ

ソッドの結果である例外の文字列表現が含まれる

Page 4: Effective Java 輪読会 項目63-65

すべてのパラメータとフィールドの値を含める

たとえば、IndexOutOfBoundsExceptionには、下記をすべて含める

下限範囲

上限範囲

範囲内に収まらなかった実際のインデックス

Page 5: Effective Java 輪読会 項目63-65

不要なものは含めなくてよい

スタックトレースは、ソースファイルと一緒に分析されるもの

例外のスロー箇所およびスタック上のすべてのメソッド呼び出しのファイルと行番号が含まれる

よって、長ったらしい説明は不要

Page 6: Effective Java 輪読会 項目63-65

例外の文字列表現とユーザレベルのエラーメッセージ

ユーザレベルのエラーメッセージエンドユーザに対してわかりやすくなければならない

例外の文字列表現

エラーを解析する際にプログラマやフィールドサービス担当者が主に使用するためのものアプレッソにおいては、開発者、サポートセンター、リセラーの担当者の方……。

疑問:特に DataSpider Servistaでは、製品の性質上(あるいは、現状の課題として?)、エンドユーザが例外を目にして自身で対処することも多いので、例外の文字列をわかりやすくすることに意義がある? できるだけエラーコードを出すようにしてます

Page 7: Effective Java 輪読会 項目63-65

例外のコンストラクタを工夫する(1)

IndexOutOfBoundsExceptionは、このようなコンストラクタを持っていればよかったのに……。

public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {

// エラーを記録する詳細メッセージを生成するsuper( "Lower bound: " + lowerBound + ", Upper bound: " + upperBound + ", Index: "

+ index);

// プログラミングによるアクセスのためにエラー情報を保存するthis.lowerBound = lowerBound;

this.upperBound = upperBound;

this.index = index;

}

Page 8: Effective Java 輪読会 項目63-65

例外のコンストラクタを工夫する(2)

エラー記録情報にアクセッサ-を提供する

チェックされる例外は、特に

エラーから回復するのに役立つ可能性がある

参照)項目58 回復可能な状態にはチェックされる例

外を、プログラミングエラーには実行時例外を使用する

チェックされない例外も、あった方がよい

参照)項目10 toStringを常にオーバーライドする

Page 9: Effective Java 輪読会 項目63-65

項目64 エラーアトミック性に努める

Page 10: Effective Java 輪読会 項目63-65

エラーアトミック性

失敗したメソッド呼び出しは、オブジェクトをそのメソッド呼び出しの前の状態にしておく

このような性質を持つメソッドは、エラーアトミックであると呼ばれる

特にチェックされる例外については重要(再び項目58)

Page 11: Effective Java 輪読会 項目63-65

エラーアトミック性を達成する方法

不変オブジェクトを用いる

操作を行う前にパラメータの正当性を検査する

エラーを捕捉し、回復するコードを書く

Copy and Swap イディオムを用いる

Page 12: Effective Java 輪読会 項目63-65

不変オブジェクトを用いる

オブジェクトが不変ならば、エラーアトミック性はコストがかからない

参照)項目15 可変性を最小限にする

Page 13: Effective Java 輪読会 項目63-65

操作を行う前にパラメータの正当性を検査する

あるいは、失敗するかもしれない部分が、オブジェクトを変更する部分よりも前に行われるようにする 例)TreeMapでは、要素の追加前に検索を行い、その時点で

ClassCastExceptionで失敗する(エラーアトミック性は保たれる)

public Object pop() {

if (size == 0)

throw new EmptyStackException();

Object result = elements[--size];

elements[size] = null; // もし検査がなければ、// ArrayIndexOutOfBoundsExceptionが潜在!

return result;

}

Page 14: Effective Java 輪読会 項目63-65

エラーを捕捉し、回復するコードを書く

主に永続的な(ディスクに基づく)データ構造に対して使用されている

あまり一般的でない方法

(Java の例外に対処する方法としては、という意味だと思います)

Page 15: Effective Java 輪読会 項目63-65

Copy and Swap イディオムを用いる

オブジェクトの一時的コピーに対して操作を行い、操作が完了したらオブジェクトの内容を一時的コピーの内容で置き換える

例)Collection.sort

Page 16: Effective Java 輪読会 項目63-65

達成可能ではない場合・望ましくない場合

たとえば ConcurrentModificationExceptionが発生したとき、回復は難しい

既にオブジェクトの整合性が保たれていない可能性が高い

エラーは、例外とは反対に、一般には回復不可能

著しくコストや複雑さが増すとき、望ましくないかもしれない

Page 17: Effective Java 輪読会 項目63-65

まとめ

メソッドの仕様の一部である例外は、オブジェクトをメソッド呼び出しの前と同じ状態にすべき

そうでない場合、API ドキュメンテーションは

オブジェクトがどのような状態に置かれるのかを明確に示すべき

Page 18: Effective Java 輪読会 項目63-65

See also:

『Exceptional C++』(Herb Sutter)

「例外安全」を掘り下げた名著

ただし、ピアソン桐原の技術書からの撤退により、日本語版は目下のところ絶版です……。

丸善の活躍に期待!(のぞみうす)

Page 19: Effective Java 輪読会 項目63-65

項目65 例外を無視しない

Page 20: Effective Java 輪読会 項目63-65

例外を無視しないようにしよう

火災警報を無視して警報を切ってしまうのと同じ!

やばすぎ

例外は目覚まし時計じゃない

最低でも、なぜ無視するのが適切なのかコメントすべき

try {

...

} catch (SomeException e) {

}

Page 21: Effective Java 輪読会 項目63-65

例外を無視するのが適切かもしれない状況の例

FileInputStreamをクローズするとき

ファイルの状態を変更していなければ、別に回復する必要もない

既に情報を読み出しているなら、あえて中断する必要もない

ただし、記録はしよう

頻繁に発生していれば、問題を調査できる

Page 22: Effective Java 輪読会 項目63-65

適用範囲

チェックされる例外

回復できるはず、回復が期待されている

回復しましょう

チェックされない例外

回復できなければ、せめて外側に伝播させて、速やかに失敗させる

問題の発生箇所と発見箇所は近ければ近いほどよいの法則