例外設計における大罪

Post on 17-Nov-2014

44.612 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

例外設計における大罪 Jun 27, 2012 @ java-ja

TRANSCRIPT

例外設計における大罪

和田 卓人 (a.k.a id:t-wada or @t_wada)Jun 27, 2012 @ java-ja

12年6月28日木曜日

自己紹介名前: 和田 卓人 (わだ たくと)

ブログ: http://d.hatena.ne.jp/t-wada

メール: takuto.wada@gmail.com

Twitter: http://twitter.com/t_wada

タワーズ・クエスト株式会社 取締役社長

12年6月28日木曜日

よろしくおねがいします

12年6月28日木曜日

例外設計における大罪

12年6月28日木曜日

無視

12年6月28日木曜日

public List<Entity> findByKeyword (String keyword)

throws Exception{ Connection conn = DriverManager.getConnection(...); PreparedStatement stmt = conn.prepareStatement( "SELECT * FROM Movie WHERE title LIKE ?"); stmt.setString(0, keyword); ResultSet rs = stmt.executeQuery(); List<Entity> entities = new ArrayList<Entity>(); while (rs.next()) { // ... } return entities;}

12年6月28日木曜日

•例外処理を行わない言い訳

•コードの流れが追いにくくなる

•納期が迫っている

•エラーが戻ることが無い関数もある

•遊びで書いただけのプログラムだから…

きのこ93: エラーを無視するな

12年6月28日木曜日

きのこ93: エラーを無視するな

•エラーを無視しても何も良いことは無い

•不安定なコード

•セキュリティ上問題のあるコード

•貧弱な構造とインターフェイス

•どうする?

•戻り値を使う

•例外を使う12年6月28日木曜日

隠蔽

12年6月28日木曜日

“try-catchブロックをコードベースに大量に入れれば、「例外が発生しても絶対に止まらない」というアプリケーションを作ることが可能なはずです。ただ、これは、もう死んでいる人の体を釘か何かで固定し、無理矢理立った状態にしているようなものですが・・・。”

きのこ27: 死ぬはずのプログラムを無理に生かしておいてはいけない

12年6月28日木曜日

}  finally  {                if  (rs  !=  null)  {                                try  {                                                rs.close();                                }  catch  (SQLException  e)  {                                                log.warn(e.getMessage(),  e);                                }                }                if  (stmt  !=  null)  {                                try  {                                                stmt.close();                                }  catch  (SQLException  e)  {                                                log.warn(e.getMessage(),  e);                                }                }                if  (con  !=  null)  {                                try  {                                                con.close();                                }  catch  (SQLException  e)  {                                                log.warn(e.getMessage(),  e);                                }                }}

遠い記憶

最近の Java に関しては try-with-resources で検索すべし12年6月28日木曜日

乱用

12年6月28日木曜日

public int sum(List<Integer> toSum) {Iterator<Integer> iter = toSum.iterator();int sum = 0;try {while(true) {sum += iter.next();

}} catch (NoSuchElementException e) {}return sum;

}

12年6月28日木曜日

•例外は、その名が示す通り、例外的条件に対してのみ使用するべきです。通常の制御フローに対しては、決して使用すべきではありません。

•上手く設計された API は、通常の制御フローに例外を使用することを、クライアントに強制してはなりません。

項目57: 例外的状態にだけ例外を使用する

12年6月28日木曜日

•「すべての例外ハンドラーを除去しても、このプログラムは動作することができるだろうか?」

•答えが「ノー」であれば、例外では無い状況下で例外が使われている

ヒント34: 例外は例外的な問題のみに使用すること

12年6月28日木曜日

過剰防御

12年6月28日木曜日

防御的プログラミングの是非

12年6月28日木曜日

package javaja;

public class Defensive {private UserRepository userRepository;public Defensive(UserRepository userRepository) {

this.userRepository = userRepository;}

public User createUser(String name, int age) {if (name == null) {

throw new NullPointerException("name is null");}if (age < 0) {

throw new IllegalArgumentException("age is negative");}if (name.isEmpty()) {

throw new IllegalArgumentException("name is empty");}User user = this.userRepository.create(name, age);return user;

}}12年6月28日木曜日

package javaja;

public class UserRepository {public User create(String name, int age) {

if (name == null) {throw new NullPointerException("name is null");

}if (age < 0) {

throw new IllegalArgumentException("age is negative");}if (name.isEmpty()) {

throw new IllegalArgumentException("name is empty");}return new User(name, age);

}}

12年6月28日木曜日

答えはあるのか

12年6月28日木曜日

契約による設計

Design by Contract (DbC)

12年6月28日木曜日

BertrandMeyer

12年6月28日木曜日

•あるルーチン(注: メソッドと読み替えても良い)におけるすべての事前条件が呼び出し側によって満足された場合、そのルーチンは作業完了時にすべての事後条件とすべての不変表明を保証する

契約による設計Design by Contract (DbC)

12年6月28日木曜日

契約による設計Design by Contract (DbC)

•冗長性のある検証は実際損傷を与える

•システム全体の視点で見るとき、シンプルさ(simplicity)が重要になる

•複雑さは品質の敵である

•過剰に防御するのではなく、誰の責任なのかをはっきりさせる

12年6月28日木曜日

契約による設計Design by Contract (DbC)

•例外処理とは、予想外の実行時状態に対処するメカニズム

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

12年6月28日木曜日

•ルーチンはリトライ(Retry)か組織的パニック(Organized Panic)のどちらかで例外を処理する

•リトライとはルーチン本体を再び実行すること

•組織的なパニックはルーチンを失敗にして、そのルーチンを呼び出したものに例外を送る

契約による設計Design by Contract (DbC)

12年6月28日木曜日

12年6月28日木曜日

おまけ12年6月28日木曜日

きのこ21: 技術的例外とビジネス例外を明確に区別する

•技術的例外とビジネス例外がある。これらを同じ例外階層構造に入れてはならない

•技術的例外は貫通させてフレームワークに任せる。ビジネス例外は準正常系なので呼び出し側で対処する

12年6月28日木曜日

“「出来てはならぬことを禁じる」のではなく、はじめから「出来ていいことだけを出来るようにする」と考えるのです。”

きのこJ6: 見知らぬ人ともうまくやるには

12年6月28日木曜日

Effective Java 2nd

•回復可能な状態にはチェックされる例外を、プログラミングエラーには実行時例外を使用する

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

•標準例外を使用する

•抽象概念に適した例外をスローする12年6月28日木曜日

Effective Java 2nd

•各メソッドがスローするすべての例外を文書化する

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

•エラーアトミック性に努める

•例外を無視しない

12年6月28日木曜日

“チェック例外の代償は、開放/閉鎖原則に違反する点です”

=> 検索すれば良質の議論が読めます

12年6月28日木曜日

まとめ12年6月28日木曜日

まとめ•例外処理/設計における大罪•無視•隠蔽•乱用•過剰防御•「契約による設計」がひとつの答え

12年6月28日木曜日

名著を読もう!

12年6月28日木曜日

ご清聴ありがとうございました

12年6月28日木曜日

top related