Effective java 輪読会 項目57-59

19
Effective Java 輪読会 2014/02/26 開発部 田中

Transcript of Effective java 輪読会 項目57-59

Page 1: Effective java 輪読会 項目57-59

Effective Java 輪読会

2014/02/26

開発部 田中

Page 2: Effective java 輪読会 項目57-59

項目57

例外的状態にだけ例外を使用する

Page 3: Effective java 輪読会 項目57-59

try-catchはいつ使うべきか

• 例外的条件でのみ使われるべきo 通常の制御フローで例外を使うと可読性を下げる

try {

int i = 0;

while(true)

range[i++].climb();

} catch (ArrayIndexOutOfBoundsException e) {

}

for (Mountain m : range) {

m.climb();

}

Page 4: Effective java 輪読会 項目57-59

これに対する我々の答えは、「例外とは予期せぬ事態に備えるためのものであり、プログラムの通常の流れの一部には組み込むべきではない」というものです。例外がプログラム中で捕捉されなかった場合、そのプログラムは停止します。このような前提を置いた上で、「すべての例外ハンドラーを除去しても、このプログラムは動作することができるだろうか?」と自問してください。答えが「ノー」であれば、例外ではない状況下で例外が使われているはずです。達人プログラマー 24 いつ例外を使用するか

Page 5: Effective java 輪読会 項目57-59

API設計も意識する

• IteratorにhasNextメソッドがない場合..

o 要素がなくなったことをcatchしなければならない

状態検査メソッドが必要

try {

Iterator<Foo> i = collection.iterator();

while(true) {

Foo foo = i.next();

}

} catch (NoSuchElementException e) {

}

Page 6: Effective java 輪読会 項目57-59

状態検査メソッド | 区別できる戻り値

• 使い分けの目安a. 同期なし並行アクセスされるか、外部要因で状態遷移する場合:状態遷移メソッド

b. 状態に依存したメソッドの処理を重複して行う必要がある場合:区別できる戻り値(かも)

Page 7: Effective java 輪読会 項目57-59

項目58

回復可能な状態にはチェックされる例外を、

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

Page 8: Effective java 輪読会 項目57-59

Javaの例外

• Javaの例外3種類a. チェック例外

b. 実行時例外

c. エラー

• Throwableo Error

o Exception

RuntimeException

Page 9: Effective java 輪読会 項目57-59

チェック例外 | 実行時例外

• 呼び出し側で適切に処理(回復)可能ならチェック例外を使用するべき

• 事前条件違反(クライアント側の債務不履行)になる場合、実行時例外がスローされるべき

• ErrorはJVMに予約されている慣例があるo 実装しない

• それ以外の独自例外はAPIを複雑にするだけ

Page 10: Effective java 輪読会 項目57-59

項目59

チェックされる例外を不必要に使用するのを避ける

Page 11: Effective java 輪読会 項目57-59

チェック例外が本当に必要か考慮する

• チェック例外は、例外を更にスローするか、クライアントコードで捌くことを強制する。o 開放-閉鎖原則に違反

o クライアントコードが複雑になりがち

o チェック例外を避ける方法がないかを考える

try-catch → if-else

Page 12: Effective java 輪読会 項目57-59

try-catch → if-else

try {

FileInputtream fin = new FileInputStream(“hoge.txt”);

...

} catch (FileNotFoundException e) {

...

}

FileInputStream2 fin = new FileInputStream2(“hoge.txt”);

if (fin.tryOpen()) {

...

} else {

...

}

Page 13: Effective java 輪読会 項目57-59

チェック例外の必要性

Page 14: Effective java 輪読会 項目57-59

契約による設計

• 「あるルーチンにおけるすべての事前条件が呼び出し側によって満足された場合、そのルーチンは作業完了時にすべての事後条件と全ての不変表明を保証する。」

• 「失敗とは、ルーチンの実行で、契約を満足させられなくなること」

Page 15: Effective java 輪読会 項目57-59

つまり

「例外は呼び出す側が契約条件を満たしたが、呼び出された側が契約を履行できなかった時に投げるもの」

Page 16: Effective java 輪読会 項目57-59

開放-閉鎖原則に違反する可能性

まず、検査例外は発生したその場、もしくは直接の呼出し元で処理しない限り、throws に記述せざるを得ない。そうしない場合、より上位層の throws を追加する必要が出てくる。このような追加、もしくは変更は、中間のクラスの再リリースという手間も必要となる。これは、明らかに開放-閉鎖原則に違反する。

Page 17: Effective java 輪読会 項目57-59

開放-閉鎖原則

モジュールは、「拡張」に対して開いており、「修正」に対して閉じていなければならない。

モジュールは、変更容易性がどの部分にあるのかを考慮して、設計されなければならない。

それにより、仕様変更時に「修正」による変更(デグレ)を行わずに、「拡張」による安全な変更を行うことができる、ということ。

Page 18: Effective java 輪読会 項目57-59

DataSpider では..

Page 19: Effective java 輪読会 項目57-59

まとまらない結論

• チェック例外は、開放-閉鎖原則に違反する使い方もできるが、即チェック例外を使用すべきとは判断できない。