きれいなコードを書くためにSOLID原則を学びました④ ~インターフェース分離の原則~


今回はSOLIDのインターフェース分離の原則についてまとめました。

その他の記事は以下。
きれいなコードを書くためにSOLID原則を学びました① ~単一責任の原則~
きれいなコードを書くためにSOLID原則を学びました② ~オープン・クローズドの原則~
きれいなコードを書くためにSOLID原則を学びました③ ~リスコフの置換原則~
きれいなコードを書くためにSOLID原則を学びました⑤ ~依存関係逆転の原則~

インターフェース分離の原則

No client should be forced to depend on methods it does not use

直訳すると、「クライアントは、使用しないメソッドに依存することを強制されるべきではない。」という意味になります。

例として、自分が複合機、プリンタスキャナー、プリンターを使うときの場合を考えてみます。
これらの機器にはそれぞれ以下の機能がついています

各機器のクラスをつくるまえに、インターフェースを用意します。
きれいなコードを書くためにSOLID原則を学びました② ~オープン・クローズドの原則~でも軽く説明しましたが、インターフェースとは、クラスに含まれるメソッドの具体的な処理内容を記述せず、変数とメソッドの型のみを定義したものです。

public interface IMultiFunction {
  public void print();

  public void scan();

  public void fax();
}

各クラスにこのインターフェースを実装すると、以下のようになります。

public class MultiDevice implements IMultiFunction {
  public void print() {
    // 印刷処理
  }

  public void scan() {
    // スキャン処理
  }

  public void fax() {
    // FAX送信処理
  }
}

public class PrinterScanner implements IMultiFunction {
  public void print() {
    // 印刷処理
  }

  public void scan() {
    // スキャン処理
  }

  public void fax() {

  }
}

public class Printer implements IMultiFunction {
  public void print() {
    // 印刷処理
  }

  public void scan() {

  }

  public void fax() {

  }
}

これはダメな実装です。
なぜなら、PrinterScannerクラスやPrinterクラスをみてみると、実装したインターフェースに対して、使わないメソッド(空のメソッド)が存在してしまっているからです。

例えば、誰かがPrinterクラスのメソッド名だけをみて、fax機能があると勘違いして使おうとしてしまうという問題が発生します。

解決法: インターフェースを分離する

以上の問題を解決する方法が、インターフェースを分離することです。
以下のように、機能ごとにインターフェースをわけます。

public interface IPrint {
  public void print();
}

public interface IScan {
  public void scan();
}

public interface IFax {
  public void fax();
}

インターフェースをわけてあげることで、存在する機能に関するインターフェースのみをクラスに実装させることができます。

public class MultiDevice implements IPrint, IScan, IFax {
  public void print() {
    // 印刷処理
  }

  public void scan() {
    // スキャン処理
  }

  public void fax() {
    // FAX送信処理
  }
}

public class PrinterScanner implements IPrint, IScan {
  public void print() {
    // 印刷処理
  }

  public void scan() {
    // スキャン処理
  }
}

public class Printer implements IPrint {
  public void print() {
    // 印刷処理
  }
}

これで処理内容が空であるメソッドを書く必要がなくなりました。

単一責任の原則を意識すればインターフェースを分離できる

インターフェースを分離するためのコツは、インターフェースの凝集度を高くすることです。
きれいなコードを書くためにSOLID原則を学びました① ~単一責任の原則~でも説明していますが、要は似た性質のメソッドでインターフェースをつくりましょう!ということですね。

おわりに

メソッドをつめこんだ大きなインターフェースをつくると、どこかでほころびがでてくることがわかりました。横着せずにインターフェースは分離しましょう。

参考書籍・動画

Crean Architecture Robert.C.Martin
SOLID Principles: Introducing Software Architecture & Design Sujith George