effective java 輪読会 第7章 項目38-40

27
Effective Java 輪輪輪 輪 6 輪輪 38 40 2014/2/12 輪輪輪 輪輪

Upload: appresso-engineering-team

Post on 27-Jun-2015

332 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Effective Java 輪読会 第7章 項目38-40

Effective Java 輪読会 第 6回(項目 38 ~ 40 )2014/2/12

開発部 野口

Page 2: Effective Java 輪読会 第7章 項目38-40

項目 38 パラメータの正当性を検査する

Page 3: Effective Java 輪読会 第7章 項目38-40

パラメータの正当性を検査する エラーが発生したらできるだけ速やかにエ

ラーを検出すべき メソッドはパラメータへの制約をメソッド本体の

初めに検査すべき

Page 4: Effective Java 輪読会 第7章 項目38-40

パラメータの正当性を検査しない場合

処理の途中で訳の分からない性外で失敗する メソッドは正常にリターンするが、何も言わ

ずに誤った結果を計算する メソッドは正常にリターンするが、いくつか

のオブジェクトを不正な状態のままにする 後になって、コードの全く関係のない箇所でエ

ラーを引き起こす 最悪!

Page 5: Effective Java 輪読会 第7章 項目38-40

例外を文書化する public のメソッドに対しては、パラメータ値

に関する制約が守られていない場合にスローされる例外を文書化する Javadoc の @throws タグを使用 IllegalArgumentException 、 IndexOutOfBou

ndsException 、 NullPointerException 等 文書化さえできれば、コードを書くのは簡単

Page 6: Effective Java 輪読会 第7章 項目38-40

アサーションを用いる 公開されていないメソッドに関しては、ア

サーションを用いてパラメータを検査する DataSpider では、独自のアサーション用ユー

ティリティクラス com.appresso.ds.common.fw.Assert を用いている

Page 7: Effective Java 輪読会 第7章 項目38-40

規則に対する例外 正当性検査のコストが高いか現実的でない かつ、正当性検査が計算の処理の中で暗黙に

行われる 例) Collections.sort(List) ただし、エラーアトミック性(項目 64 )に注意

が必要 失敗したメソッド呼び出しは、オブジェクトをそのメ

ソッド呼び出しの前の状態にしておくべき

Page 8: Effective Java 輪読会 第7章 項目38-40

注意:制約はよいものではない 制約がなくなるくらい、メソッドを一般的に

設計すべき 実際には、制約がやむをえない場合が多いの

で、その際は文書化し、チェックする

Page 9: Effective Java 輪読会 第7章 項目38-40

まとめ メソッドあるいはコンストラクタを書く際に

は、パラメータの制約を考える 制約を文書化する メソッド本体のはじめで明示的に検査し、制

約を強制する

Page 10: Effective Java 輪読会 第7章 項目38-40

項目 39必要な場合には、防御的にコピーする

Page 11: Effective Java 輪読会 第7章 項目38-40

Java は安全な言語 バッファオーバーランを始めとするメモリ破

壊エラーに対して、免疫がある (疑問:「免疫がある」ということ

は、 completely free というわけではない?)

Page 12: Effective Java 輪読会 第7章 項目38-40

それでも守る努力は必要 クラスのクライアントは、クラスの不変式を

破壊するために徹底した努力をする と想定して防御的にプログラムすべき

セキュリティを破ろうとする悪意のプログラマ よりも、むしろ使用者の単純なミスが問題

Page 13: Effective Java 輪読会 第7章 項目38-40

セキュリティホールの例 pp.178 Period クラス

コンストラクタで渡した Date を、渡したあとも変更できる( pp.179 )

start / end メソッドの戻り値を変更することで、Period の内部を変更できる( pp.180 )

Page 14: Effective Java 輪読会 第7章 項目38-40

セキュリティホールへの対処 コンストラクタで、防御的コピー

( pp.179 ) TOCTOU 攻撃に備えるため、コピーに対して正

当性を検査する サブクラス化に対処するため、 clone メソッド

を使用しない アクセッサ-でも、防御的コピー

( pp.180 )

Page 15: Effective Java 輪読会 第7章 項目38-40

本当の教訓 可能な場所では、オブジェクトの構成要素と

して不変オブジェクトを使用する 例) Date ではなく、 Date.getTime() の戻り

値( long )を用いる

Page 16: Effective Java 輪読会 第7章 項目38-40

トレードオフ パフォーマンス上のペナルティはありうる

クラスとその呼び出し元が同じパッケージの一部であるような場合には、防御的コピーを行わず、かわりにドキュメンテーションで済ませるといった手もある

Page 17: Effective Java 輪読会 第7章 項目38-40

制御の移転 パッケージ境界を越えるとしても、あえて防

御的にコピーしないケース ドキュメンテーションに制御の移転が必要で

あることを示し、クライアントはそれに従う 例)ラッパークラス

ラッパークラスでは、一般に制御を移転したあとにオブジェクトを変更した場合に、クライアント自身にのみ害を及ぼす

Page 18: Effective Java 輪読会 第7章 項目38-40

まとめ クラスがそのクライアントから得たり、クラ

イアントへ返したりする可変の要素を持っているならば、防御的にコピーする

コピーのコストが非常に高く、クライアントが要素を不適切に変更しないことを信頼できるなら、その旨をドキュメンテーションに示す

Page 19: Effective Java 輪読会 第7章 項目38-40

項目 40メソッドのシグニチャを注意深く設計する

Page 20: Effective Java 輪読会 第7章 項目38-40

メソッド名を注意深く選ぶ

理解可能 同じパッケージ内の他の名前と矛盾がない 広範囲のコンセンサスと矛盾がない

Java ライブラリーの API がガイダンスになる まあ、ところどころ矛盾もあるけど……。

大きさとか、歴史的な経緯とか

Page 21: Effective Java 輪読会 第7章 項目38-40

便利なメソッドを提供し過ぎたりしないようにする 個々のメソッドは、「自分の役割を果たす」こ

と 型がサポートしている個々の処理について完全

に機能すること 速記法は本当に頻繁に使用され、明らかに役に立つ場合だけ

特にインタフェースには注意 多くのメソッドを持つインタフェースはユーザお

よび実装者の人生を複雑にする人生、シンプルな方が(精神衛生上)よい

Page 22: Effective Java 輪読会 第7章 項目38-40

長いパラメータのリストは避ける

4 個以下を目標に マジックナンバー 7±2 という説もありますね

同じ型のパラメータが何個も続くのは特に有害 順序を間違えてもコンパイルエラーにならない

Page 23: Effective Java 輪読会 第7章 項目38-40

パラメータリスト短縮法その1

メソッドを複数のメソッドに分割する 直交性を増加させ、メソッド数を減らすこともで

きる 例) java.util.List の subList メソッド

と、 indexOf / lastIndexOf メソッド

Page 24: Effective Java 輪読会 第7章 項目38-40

パラメータリスト短縮法その2

ヘルパークラス static のメンバークラス 例)カードゲームを表すクラスにおいて、ランク

とスートを常に同時に扱っているなら、「カード」ヘルパークラスを導入する

Page 25: Effective Java 輪読会 第7章 項目38-40

パラメータリスト短縮法その3

ビルダーパターンの応用 saucepan.water(400).sugar(5).salt(10).cube

(Cube.Chicken, 2).cook()

Page 26: Effective Java 輪読会 第7章 項目38-40

パラメータ型に関しては、クラスよりインタフェースを選ぶ たとえば、 HashMap ではなく Map を使う

たまたま HashMap 以外の Map を持っているクライアントを煩わせずにすむ

参照)項目 52 インタフェースでオブジェクトを参照する『実装パターン』( Kent Beck )にも同様の議論が

ありました

Page 27: Effective Java 輪読会 第7章 項目38-40

boolean パラメータより 2 つの要素を持つ enum 型を使用する 読みやすくなる IDE のコード補完を活用できる オプションを追加しやすい メソッドへのリファクタリングも可能