Edited at

EffectiveJava読書会7日目 - 第7章 メソッド

More than 5 years have passed since last update.

38: メソッドの入力値チェックはしましょう

39: setterがなくてもフィールドっていじれるのですよ?

40: tips集。よく読め。

41: 同じパラメータ数のメソッドを複数作ってオーバーロードするのはやめとけ。

42: 可変長引数の使い方 ~便利だからって変な使い方スンナよ~

43: nullではなく、空配列か空コレクションを返す。null処理メンドイんじゃ。

44: Javadoc書きなさい。



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


  • はじめにパラメータを検査する処理を入れましょう
     →nullじゃだめとか

  • 適切なExceptionをスローしましょう
    IllegalArgumentException、IndexOutOfBoundsException、NullPointerException
    -publicのメソッドに対しては、パラメータ値に関する制約が守られていない場合にスローされる例外を、Javadocの@throwsタグを使用して文書化してください
    @throws ArithmethicException m <= 0 の場合

  • パブリックでないメソッド
    →勝手になんか入れられることは無いので、正統なパラメータ値だけが渡されることは保証されている
    「assert」をつかう

******************

Assertion Java1.4から導入

AssertionError がスローされる

有効にするには実行時のオプションに-eaが必要

(無効にした場合、何のコストもかからない)

パブリックメソッドで使っちゃだめ(IllegalArgumentException、IndexOutOfBoundsException、NullPointerException などをスローするべき)

→デバッグ用?

******************

制限かけてるやつがかっこいいんじゃないよ 制限無くて一般的なほうが本当はいいよ


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

うっかりプログラマさんが余計なことしやがるかもしれない。

private final Date start

private final Date end

これ、コンストラクタで外からオブジェクト受け取ってるので、普通に書きかえられるから。

「防御的にコピー」してください。

getterの返り値もNewしてCopyすれば安全!

※防御的コピーはパフォーマンスの低下を招く

不変オブジェクト(項目15。String,ボクシングされた基本データクラス、BigInteger、 BigDecimal)を内部で使えば安心

ラッパークラス(項目16)を使えば、元とインスタンスが換わっているので、改変されても他の人へは害が及ばない

 → うーんわからん。

 

トレードオフなので、「影響を受ける要素を変更しないことがクライアントの責任である とドキュメントに書いて防御的コピーの代わりにするのもOK」


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

シグニチャ=

メソッドのシグネチャの一般的な意味

シグネチャとは日本語にすると「署名」などの意味ですが、一般的なプログラミング言語(特にオブジェクト指向言語)におけるシグネチャも正にそういう意味で、唯一無二であることを示すためのもの(=メソッドの署名)です。1つのメソッドは基本的に1つのシグネチャを持っています。このようにシグネチャを持つことで、それぞれのメソッドがコンパイラなどで明確に区別できるわけです。

このシグネチャには、一般的には、「メソッド名」「パラメータ数と順序、パラメータの型」「戻り値の型」が含まれると考えられています。なお当然ながら、JavaやC#などで文の終わりを示す「;」はシグネチャには含めません。

しかしここで注意が必要です。実際には、現在の大半のプログラミング言語(Java言語やC#/VB言語、C++言語など)では「戻り値の型(return type)」をシグネチャに含めないからです。

メソッド名

・理解可能であること

・パッケージ内のほかの名前と矛盾しないこと

・存在する広範囲のコンセンサスと矛盾が無いこと

・わからなければJavaライブラリのAPIを見てみよう

:標準命名規約(項目56)

 活字的命名規約(メソッド名関連のもの):

  1つかそれ以上の単語から構成され、個々の単語の最初の文字は大文字(ただし、メソッド名の先頭は小文字)

  頭字語(頭文字を一字ずつアルファベットの名のままで読むもの。HTTP的な。)および、maxやminなどの一般的な省略形以外、省略しない

  メソッド名では、頭字語が頭にきたら全部小文字であるべき。(hTTPみたいのは避ける。クラスの場合は、HTTPは使えることもある)

 文法的命名規約

  何からの処理をするメソッドは動詞あるいは目的語を含む動詞句で命名 append, drawImage

  booleanを返すメソッドはisで始まる。まれにhasではじまる isDigit, isProbablePrime, hasSiblings

  呼び出されたオブジェクトの、boolean以外の機能や属性を返すメソッド 名詞、名詞句、get○○ size, hashCode, getTime

   get...パターンだけが許されるといっている人もいるが、初めの二つは読みやすい場合が多い

    ※JavaBeansを作るならgetが必須

    ・・・

便利なメソッドを提供しすぎない

 クラスにメソッドが多すぎると、クラスの学習、仕様、文書化、テスト、保守などを困難にする

 インタフェースにメソッドが多すぎると、実装者が大変

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

 4個以下目標!

 特に、同じ型が続くと事故の恐れあり。

  引数を減らすために

   メソッドを分割する

    Listインタフェースは「サブリストに対して○○をする」というメソッドは提供していない。

    サブリストを提供するViewのみ。その返り値に対して他のメソッドを組み合わせることが可能。

   パラメータの集まりを保持するパラメータクラスを作る

    カードゲームをやってて、数字とスートを常に引数にとるんだったら、カードクラスを作ったほうがいい

    →※それはわかるんだけど、なんでstaticなメンバークラス(項目22)?

   ビルダーパターン(項目2)をメソッド呼び出しに適用

    =デフォルトパラメータを持つコンストラクタ。必要なものだけSetterで書き換える。

パラメータの型はクラスよりインタフェース

 →そっちのほうが使いやすい

パラメータはbooleanより2つの要素を持つenum

 下のほうが読みやすいよね?

  Thermometer.newInstance(true)

  Thermometer.newInstance(TemperatureScale.CELSIUS)

 こうやっておけばTemperatureScaleに種類を追加することも可能


項目41 オーバーロードを注意して使用する**

P184の例はちゃんと動かない!

→オーバーロードは動作時にどのメソッドが呼び出されるかが動的に決まるため、原因の究明も困難。

・同じ引数の数のオーバーロードは避けるべき

※これは知らんかったわ… 気をつけよう。


項目42 可変長引数を注意して使用する

可変引数メソッドは1.5から。

メソッド内へは引数で渡される。

・ひとつ以上の引数が欲しい場合、一つ目の引数を独立したパラメータにしましょう

・最後の引数が配列のものを全部置き換えてはいけない

 ・もともとコンパイルエラーだったケースがコンパイルエラーじゃなくなってて云々かんぬん

・コストパフォーマンスはあまりよくない。

 パフォーマンスを出すなら、オーバーロードを使ってそれぞれの引数の数のメソッドを作るのと併用するとよい。

 ※EnumSetの内部では使用されている

 普通は問題になるレベルじゃないけどね。


項目43 nullではなく、空配列か空コレクションを返す**

・nullを返していると、受け取った側で処理しないといけないです

※これいつも悩んでたんですが、今日からこうやります!


項目44 すべての公開API要素に対してドキュメントコメントを書く**

すべてのPublicなものにはJavadocコメントを書きましょう。

・ドキュメントコメント

 メソッドのすべての事前条件と事後条件を列挙する

  ・事前条件(クライアントがメソッドを呼び出すために成立していなければならない事柄)

   →@throwsで暗黙に記述される

   →または@paramsでパラメータに記述する

  ・事後条件(呼び出しが正常に完了した後に成立していなければならない事柄)

 副作用もすべて記述すること

 スレッド安全性について記述すること

 

 @params, @return, @throwsがすべてに対してかかれるべき

  @params, @return は名詞句が続く

  @throwsはifから始まる

 @code

  プログラムの一部を記述するために使用。HTMLエスケープの必要がない

 "this"

  メソッドが呼び出されたオブジェクトをさす ※コード中のthisと同じですね

 @literal

  @codeににているが、コードフォントで表示されない。不等号や、ピリオドを遣うときに使用するとよい。

 

 説明は普通、文ではない

  メソッド説明は動詞句。

  クラス、インタフェース、フィールドは名詞句。

  ジェネリック型、ジェネリックメソッド すべての方パラメータを文書化

  enum 定数も文書化

  アノテーション すべてを文書化