読み込み中...

SOLID原則のインターフェース分離の原則(ISP)についてRubyで解説

プログラミング #ruby #SOLID #オブジェクト指向 #クリーンコード
2024年5月13日
2024年6月6日
SOLID原則のインターフェース分離の原則(ISP)についてRubyで解説

オブジェクト指向プログラミングにおいて、コードの保守性、可読性、再利用性を高めるために、SOLID原則と呼ばれる5つの重要な設計原則があります。

今回は、このSOLID原則のうち、インターフェース分離の原則(Interface Separation Principle, ISP)についてRubyのサンプルコードを用いて解説していきます。

SOLIDとは

SOLIDとは、5つの原則の頭文字を取った略語です。

  1. Single Responsibility Principle(SRP): 単一責任原則
  2. Open Closed Principle(OCP): オープン・クローズドの原則
  3. Liskov Substitution Principle(LSP): リスコフの置換原則
  4. Interface Separation Principle(ISP): インターフェース分離の原則
  5. Dependency Inversion Principle(DIP): 依存性逆転の原則

インターフェース分離の原則 (Interface Separation Principle, ISP)とは

インターフェース分離の原則は、インターフェースを利用する具像クラスが使用しないメソッドに依存することを避けるため、インターフェースを細分化するという原則です。

巨大で複雑なインターフェースの代わりに、ニーズに特化した小さなインターフェースを作成します。

いわゆるインターフェース版の単一責任原則ですね。

主に以下のメリットがあると思います。

  1. インターフェースを指定している呼び出す側から、無関係なメソッドが見えなくなるため使い方がシンプルになる。
  2. ニーズに特化し小さくすることで、呼び出されるメソッドを限定することができるため問題分析しやすくなる。
  3. 別の具像クラスに変更するとき、小さくしたインターフェースのメソッドだけを満たすだけで良く、変更が容易になる。

以降、解説していきます。

インターフェース分離の原則に違反しているコード

正直に言いますと、Rubyでは正しくサンプルコードを書くことが出来ません。

なぜなら、Rubyは言語的にダックタイピングの思想を用いており、インターフェースという仕組みがないためです。

JavaやTypeScriptであれば、具象クラスを作成する際、インターフェースにより不要なメソッドの作成を強制されるので、わかりやすいサンプルコードを書くことができるのですが、前述の理由により、Rubyだと難しくなります。

少し強引ですが、抽象クラスを用いて解説してみます。

以下のようなクラスがあったとします。

class Worker
  def work
    raise NotImplementedError, 'Subclasses must implement work method'
  end

  def eat
    raise NotImplementedError, 'Subclasses must implement eat method'
  end

  def sleep
    raise NotImplementedError, 'Subclasses must implement sleep method'
  end
end

class Employee < Worker
  def work
    # ...
  end

  def eat
    # ...
  end

  def sleep
    # ...
  end
end

class Robot < Worker
  def work
    # ...
  end

  def eat
    raise NotImplementedError, 'Robots do not eat'
  end

  def sleep
    raise NotImplementedError, 'Robots do not sleep'
  end
end

この例では、Worker抽象クラスがwork、eat、sleepメソッドを定義していますが、Robotクラスはeatsleepメソッドを使用しません。これはインターフェース分離の原則に違反しています。

インターフェース分離の原則に則ったコード

以下のようにすることで改善出来ます。

class Worker
  def work
    raise NotImplementedError, 'Subclasses must implement work method'
  end
end

module LivingBeing
  def eat
    raise NotImplementedError, 'Subclasses must implement eat method'
  end

  def sleep
    raise NotImplementedError, 'Subclasses must implement sleep method'
  end
end

class Employee < Worker
  include LivingBeing

  def work
    # ...
  end

  def eat
    # ...
  end

  def sleep
    # ...
  end
end

class Robot < Worker
  def work
    # ...
  end
end

この例では、RobotクラスはWorker抽象クラスのみを継承し、不要なメソッドに依存しません。これにより、インターフェース分離の原則に準拠したコードになります。

これはあくまでもRubyで強引に解説しようとしたコードであり、現実的に使用するかというとそうではありません。(基本的にRubyではダックタイピングを用い、インターフェースをコードに落とし込むことはしないため。)

最後に

今回の原則で見えてきたことは、SOLID原則やデザインパターンなど、世には様々なプログラミングに関する原則がありますが、これら全てに従うのが正しいのではなく、言語特性やプロダクト特性などによって使い分けをしていく必要があるということです。

そのためにもそれぞれの原則を正しく理解し、将来的に負債とならないか?を突き詰めて適用していく必要があります。

こういった分野は、経験がものを言うと思いますので、日々、betterな設計がないか?を模索していくことが大事だと思います。



システム開発やDX戦略などでお困りの際はお気軽にご相談ください。

※通常1営業日以内に回答致します。

お問い合わせはこちら
Top