# 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 endend
class Service def call LoggerService.call('Something happened') endend
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') endend
# Now you can inject any logger service you want into the Service classservice = Service.new(logger_service: LoggerService)service.call
依存関係の逆転の説明
依存関係の逆転の原則は、オブジェクト指向設計のSOLID5原則の1つである。
- 高レベルモジュール(クラスやコンポーネントなど)は、低レベルモジュールに依存してはならない。
- 抽象化は詳細に依存すべきではない。 詳細(具体的な実装)は抽象に依存する必要があります。
提供されたコード例のコンテキストでは、Service クラスは高レベルモジュールと見なされ、LoggerService クラスは低レベルモジュールと見なされます。 依存性注入を使用することで、Service クラスは LoggerService クラスの特定の実装に依存しなくなり、代わりに抽象化(つまり、params 引数を受け入れる呼び出しメソッドを持つオブジェクト)に依存します。
これは依存性の逆転の原則に従います。なぜなら、高レベルの Service クラスは、低レベルのモジュール(LoggerService クラス)ではなく、抽象化(logger_service
オブジェクト)に依存するからです。 また、詳細(LoggerService クラスの具体的な実装)が抽象(logger_service
オブジェクト)に依存するため、この原則に従います。
全体として、依存性注入を使用し、依存性の逆転の原則に従うことで、ソフトウェアの設計とアーキテクチャを改善することができます。