Publicité

例外設計における大罪

Chief Executive Programmer à Towersquest
27 Jun 2012
Publicité

Contenu connexe

Présentations pour vous(20)

Publicité
Publicité

例外設計における大罪

  1. 例外設計 における大罪 和田 卓人 (a.k.a id:t-wada or @t_wada) Jun 27, 2012 @ java-ja 12年6月28日木曜日
  2. 自己紹介 名前: 和田 卓人 (わだ たくと) ブログ: http://d.hatena.ne.jp/t-wada メール: takuto.wada@gmail.com Twitter: http://twitter.com/t_wada タワーズ・クエスト株式会社 取締役社長 12年6月28日木曜日
  3. よろしく おねがい します 12年6月28日木曜日
  4. 例外設計 における大罪 12年6月28日木曜日
  5. 無視 12年6月28日木曜日
  6. 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日木曜日
  7. きのこ93: エラーを無視するな • 例外処理を行わない言い訳 • コードの流れが追いにくくなる • 納期が迫っている • エラーが戻ることが無い関数もある • 遊びで書いただけのプログラムだか ら… 12年6月28日木曜日
  8. きのこ93: エラーを無視するな • エラーを無視しても何も良いことは無い • 不安定なコード • セキュリティ上問題のあるコード • 貧弱な構造とインターフェイス • どうする? • 戻り値を使う • 例外を使う 12年6月28日木曜日
  9. 隠蔽 12年6月28日木曜日
  10. きのこ27: 死ぬはずのプログラムを 無理に生かしておいてはいけない try-catchブロックをコードベースに 大量に入れれば、「例外が発生しても 絶対に止まらない」というアプリケー ションを作ることが可能なはずです。 ただ、これは、もう死んでいる人の体 を釘か何かで固定し、無理矢理立った 状態にしているようなものです が・・・。 12年6月28日木曜日
  11. }  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. 乱用 12年6月28日木曜日
  13. 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日木曜日
  14. 項目57: 例外的状態にだけ 例外を使用する • 例外は、その名が示す通り、例外的条 件に対してのみ使用するべきです。通 常の制御フローに対しては、決して使 用すべきではありません。 • 上手く設計された API は、通常の制御 フローに例外を使用することを、クラ イアントに強制してはなりません。 12年6月28日木曜日
  15. ヒント34: 例外は例外的な 問題のみに使用すること • 「すべての例外ハンドラーを除去して も、このプログラムは動作することが できるだろうか?」 • 答えが「ノー」であれば、例外では無 い状況下で例外が使われている 12年6月28日木曜日
  16. 過剰 防御 12年6月28日木曜日
  17. 防御的プログラミング の是非 12年6月28日木曜日
  18. 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日木曜日
  19. 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日木曜日
  20. 答えは あるのか 12年6月28日木曜日
  21. 契約による 設計 Design by Contract (DbC) 12年6月28日木曜日
  22. Bertrand Meyer 12年6月28日木曜日
  23. 契約による設計 Design by Contract (DbC) • あるルーチン にお (注: メソッドと読み替えても良い) けるすべての事前条件が呼び出し側に よって満足された場合、そのルーチン は作業完了時にすべての事後条件とす べての不変表明を保証する 12年6月28日木曜日
  24. 契約による設計 Design by Contract (DbC) • 冗長性のある検証は実際損傷を与える • システム全体の視点で見るとき、シン プルさ(simplicity)が重要になる • 複雑さは品質の敵である • 過剰に防御するのではなく、誰の責任 なのかをはっきりさせる 12年6月28日木曜日
  25. 契約による設計 Design by Contract (DbC) • 例外処理とは、予想外の実行時状態に対 処するメカニズム • 失敗とは、ルーチンの実行で、契約を満 足させられなくなること 12年6月28日木曜日
  26. 契約による設計 Design by Contract (DbC) • ルーチンはリトライ(Retry)か組織的パ ニック(Organized Panic)のどちらかで 例外を処理する • リトライとはルーチン本体を再び実行 すること • 組織的なパニックはルーチンを失敗に して、そのルーチンを呼び出したもの に例外を送る 12年6月28日木曜日
  27. 12年6月28日木曜日
  28. おまけ 12年6月28日木曜日
  29. きのこ21: 技術的例外とビジネ ス例外を明確に区別する • 技術的例外とビジネス例外がある。こ れらを同じ例外階層構造に入れてはな らない • 技術的例外は貫通させてフレームワー クに任せる。ビジネス例外は準正常系 なので呼び出し側で対処する 12年6月28日木曜日
  30. きのこJ6: 見知らぬ人ともうまくやるには 「出来てはならぬことを禁じる」の ではなく、はじめから「出来ていいこ とだけを出来るようにする」と考える のです。 12年6月28日木曜日
  31. Effective Java 2nd • 回復可能な状態にはチェックされる例 外を、プログラミングエラーには実行 時例外を使用する • チェックされる例外を不必要に使用す るのを避ける • 標準例外を使用する • 抽象概念に適した例外をスローする 12年6月28日木曜日
  32. Effective Java 2nd • 各メソッドがスローするすべての例外 を文書化する • 詳細メッセージにエラー記録情報を含 める • エラーアトミック性に努める • 例外を無視しない 12年6月28日木曜日
  33. チェック例外の 代償は、開放/ 閉鎖原則に違反 する点です => 検索すれば良質の議論が読め ます 12年6月28日木曜日
  34. まとめ 12年6月28日木曜日
  35. まとめ • 例外処理/設計における大罪 • 無視 • 隠蔽 • 乱用 • 過剰防御 • 「契約による設計」がひとつの答え 12年6月28日木曜日
  36. 名著を読もう! 12年6月28日木曜日
  37. ご清聴ありがとうございました 12年6月28日木曜日
Publicité