Noriyo Akita's Today I Learned

# 2024-07-20

Table of Contents

2024-07-20

How to implement Dependency Injection Pattern in Ruby On Rails?

https://dev.to/vladhilko/how-to-implement-dependency-injection-pattern-in-ruby-on-rails-28d6

class LoggerService
def self.call(params)
puts params
end
end
class Service
def call
LoggerService.call('Something happened')
end
end
Service.new.call

このハードコードアプローチの問題点:

  • SOLIDの依存関係逆転の原則に反する
  • クラスの内部メソッドを更新する必要があるため、コードを変更するのはかなり難しく、何かを壊してしまう危険性がある
  • 内部でハードコードされたサービスをたくさん使い始めると、読んで理解するのが難しくなる。 例えば、ハードコードされたサービスは複数の名前空間(Namespace1::Namespace2::LoggerServiceなど)の下にある可能性があるので、本当に「認知的負荷」が増えます)。

Plain Ruby Dependency Injection

記事では dry gem を使った例もあるがやらない

class Service
attr_reader :logger_service
def initialize(logger_service:)
@logger_service = logger_service
end
def call
logger_service.call('Something happened')
end
end
# Now you can inject any logger service you want into the Service class
service = Service.new(logger_service: LoggerService)
service.call

依存関係の逆転の説明

依存関係の逆転の原則は、オブジェクト指向設計のSOLID5原則の1つである。

  • 高レベルモジュール(クラスやコンポーネントなど)は、低レベルモジュールに依存してはならない。
  • 抽象化は詳細に依存すべきではない。 詳細(具体的な実装)は抽象に依存する必要があります。

提供されたコード例のコンテキストでは、Service クラスは高レベルモジュールと見なされ、LoggerService クラスは低レベルモジュールと見なされます。 依存性注入を使用することで、Service クラスは LoggerService クラスの特定の実装に依存しなくなり、代わりに抽象化(つまり、params 引数を受け入れる呼び出しメソッドを持つオブジェクト)に依存します。

これは依存性の逆転の原則に従います。なぜなら、高レベルの Service クラスは、低レベルのモジュール(LoggerService クラス)ではなく、抽象化(logger_service オブジェクト)に依存するからです。 また、詳細(LoggerService クラスの具体的な実装)が抽象(logger_service オブジェクト)に依存するため、この原則に従います。

全体として、依存性注入を使用し、依存性の逆転の原則に従うことで、ソフトウェアの設計とアーキテクチャを改善することができます。

My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts