Madogiwa Blog

主に技術系の学習メモに使っていきます。

Rubyで学オブジェクト指向 SOLID原則「依存性逆転の原則(Dependency inversion principle)」

Clean Architecture 達人に学ぶソフトウェアの構造と設計を読んで、オブジェクト指向の原則について学びがあったので、Rubyのコード例と共に内容を整理してみました。

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

※私の学びのメモなので理解が間違ってる可能性があります、間違ってたらすいません🙇‍♂️

依存性逆転の原則(Dependency inversion principle)とは

具体ではなく、抽象に依存しなければならない https://ja.wikipedia.org/wiki/SOLID

依存性逆転の原則とは、記載の通り変更が発生しやすい具体的なクラスや振る舞いではなく、より変更が発生しにくい抽象的なクラスや振る舞いに依存するように設計しましょうという原則ですね。

依存性逆転の原則の例とコード

依存性逆転の原則を意識できていないコードと例

例えば下記のような仕様があったとします。

  • ユーザーは投稿(Post)を投稿できる
  • 投稿は必ずユーザーを持つ
  • ユーザーが投稿するときは公開済みで投稿が作成される

この仕様を満たすコード例を下記に記載しました。

class User
  def create_post(attributes)
    post = Post.new(attribute)
    post.user = self
    post.published = true
    post.save
  end
end

class Post
  attr_accesser :title, :body :user, :published
end

User#create_postでユーザーに紐づく公開済みの投稿を登録するようにしてみました。

実際にコードを読み返してみるとUser#create_postは投稿が公開済みフラグを持つことや、保存用のメソッドを持つこと等、具体的な挙動に依存した実装となってしまい、投稿側の仕様変更の影響を受けやすいコードになってしまっています。

また依存関係を考えると投稿は必ずユーザーを持つため、ユーザーのほうが投稿よりも上位のクラスであることが読み取れます。 一般的に上位のクラスより下位のクラスのほうが変更頻度は高い(抽象度が低い)ため、影響を受ける頻度も高そうです。。。

依存性逆転の原則を意識してリファクタリングしてみる

依存性逆転の原則を意識して、具体的な実装に依存しないようにUserPostというクラスを介してUser#create_post実行時にユーザーと紐付いた公開済みの投稿と登録するようにしました。

class User
  def create_post(attributes)
    UserPost.create(attributes, self)
  end
end

class UserPost
  def create(attributes, user)
    post = Post.new(attribute)
    post.user = user
    post.published = true
    post.save
  end
end

class Post
  attr_accesser :title, :body :user, :published
end

これによってUser#create_postは下位クラスであるPostの具体的な挙動には関心を持たなくなり、影響を受けなくなりました。さらにユーザーが投稿するときは公開済みで投稿が作成されるといった具体的な挙動についての責任はUserPost側が持つことになり、仮に下書き機能等が追加され前提が崩れたとしてもUser#create_postは影響を受けず、UserPost側の実装を治すだけでよくなり現状よりも抽象的なクラスになりました🙌

おわりに

今回はオブジェクト指向のSLID原則「インターフェイス分離の原則(Interface segregation principle)」について自分の理解をRubyのコード例とともに説明してみました。

User#create_postは下位クラスであるPostの具体的な挙動には関心を持たなくなり

リファクタリングの部分で記載したようにもともと下位クラスの振る舞いに依存していたものが、下位クラスの挙動が上位クラスの期待に依存するように変更されています。このように修正されるから依存性逆転の原則と呼ばれるのかなと思いました👀

(Railsリファクタリングで使われるFormObjectとかも、この原則にあたるんですかね?🤔)

今回でSOLID原則は最終回です、ありがとうありがとうございました🙇‍♂️

参考

Clean Architecture 達人に学ぶソフトウェアの構造と設計

Clean Architecture 達人に学ぶソフトウェアの構造と設計

www.techscore.com

github.com