Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

例外設計における大罪

70,924 views

Published on

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

Published in: Technology
  • Be the first to comment

例外設計における大罪

  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日木曜日

×