読者です 読者をやめる 読者になる 読者になる

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

Java Effective Java

ここでは独立して項目を作るほどではないような API 設計時のヒントを説明します。

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

メソッドに限らず名前は常に標準命名規約に従うべきです。 理解可能で同じパッケージの他の名前と矛盾しない内容にするべきです。

さらに、一般的なコンセンサスと矛盾がないようにしましょう。 Java ライブラリの API はたくさんの矛盾を抱えていますが、それでもかなりのコンセンサスが存在しています。

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

一つ一つのメソッドは自分の役割にのみ集中するべきです。

多くのメソッドを用意すると、学習、使用、文書化、テスト、保守を困難にします。 頻繁に行われる操作にだけ追加で便利メソッドを用意するべきです。

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

パラメータは 4 個以下を目標にしてください。 特に同じ型のパラメータが続くことは避けるべきです。

長いパラメータリストを避けるテクニックは3つあります。

  • 長いパラメータのメソッドを、複数のメソッドに分割する
  • シンプルなパラメータクラスを作成する
  • ビルダーパターンをパラメータクラスに適用する

パラメータの宣言型はインタフェースを選ぶ

パラメータとして受け付ける型は実装クラスよりもインタフェースを使用するべきです。

たとえば、入力として HashMap を取るメソッドでは、パラメータ型として Map 型を宣言したほうがいいです。 Map として宣言しておけば、HashMap、TreeMap、その他の新しい実装 Map を使うことができます。

もし、HashMap として宣言してしまった場合、どうなるでしょうか。 メソッドを使うために TreeMap から HashMap にコピーしなおす、という作業をクライアントがわざわざすることになるかもしれません。

boolean は二つの要素を持つ enum にする

2つの状態を持つ変数を作る場合、boolean よりも2個の要素をもつ Enum を定義したほうがプログラムが分かりやすくなります。

たとえば、摂氏と華氏に対応した温度計を表す Thermometer クラスを考えてみます。 単純な方法として isCelsius パラメータを、もとにそれぞれのインスタンスを返す実装が考えられます。

public class Thermometer {
    public static class newInstance(boolean isCelsius) {
        if (isCelsius) {
            return new CelsiusThermometer();
        } else {
            return new FahrenheitThermometer();
        }
    }
}

これよりも、CELSIUS と FAHRENHEIT をもつ TemperatureScale 型を定義したほうが分かりやすいでしょう。

public class Thermometer {
    public enum TemperatureScale { FAHRENHEIT, CELSIUS }
    public static class newInstance(TemperatureScale scale) {
       switch (scale) {
           case CELSIUS:
               return new CelsiusThermometer();
           case FAHRENHEIT:
               return new FahrenheitThermometer();
       }
    }
}

こうすれば新たな KelvinThermometer も簡単に追加することができるでしょう。

感想

「パラメータは4個以下」、「状態変数は boolean よりも enum」という2つに関しては CODE COMPLETE にも同じようなことが書いてあった。

そういえば、ようやく Item 40 まできた。