例外設計における大罪

59,517 views
58,736 views

Published on

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

Published in: Technology
0 Comments
226 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
59,517
On SlideShare
0
From Embeds
0
Number of Embeds
4,991
Actions
Shares
0
Downloads
248
Comments
0
Likes
226
Embeds 0
No embeds

No notes for slide

例外設計における大罪

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

×