LoginSignup
0
0

More than 3 years have passed since last update.

RubyでDIしてみた

Last updated at Posted at 2020-10-12

DIとは

dependency injection (依存性注入)のこと

外からconstractorにobject渡せるようにすることで依存を避けようっていうもの

実装

Interactorを例に書いていく
dry-containerdry-auto_injectを使ってDIしてみた

DIしてない版

not_di.rb

module Interactor
  class FindUser
    def initialize(params)
      @params = params
    end

    def call
      user_repo = UserRepository.new
      user_repo.by_pk(@params[:id])
    end
  end
end

UserRepositoryに依存しているのがわかる

dry-container使わない版

pure-di.rb

module Interactor
  class FindUser
    def initialize(params: {}, user_repo: UserRepository.new)
      @params = params
      @user_repo = user_repo
    end

    def call
      @user_repo.by_pk(@params[:id])
    end
  end
end

initializdの引数がでっかくなってみづらいコードになりがち
これありますねぇ

dry-container版

dry-di.rb
module Container
  module FindUser
    extend Dry::Container::Mixin

    # 注入するobjectを登録していく
    # blockでdefaultのobjectを宣言できる
    register "params"

    register "user_repo" do
      UserRepository.new
    end
  end
end


module Interactor
  class FindUser
    Import = Dry::AutoInject(Container::FindUser)
    # includeしたものをmethodで呼び出せるようになる
    include Import["params", "user_repo"]

    def call
      user_repo.by_pk(params[:id])
    end
  end
end

コードは増えたけど責務を切り分けることで見通しがよくなった

InteractorがContainerに依存していて、呼び出す人(Controllerとか)もContainerに依存しているので
いい感じに依存性を逆転させることができた

before: controller -> interactor
after: controller -> container <- interactor

何が嬉しいのか

  • コードがスッキリする

initializeをcontainerに委託することでinteractorの責務が減った
classあたりの責務は減らしていきたい

  • 単体テストが簡単にできる

InteractorのテストをDB用意しないでできる
上の例だと by_pk(id) に反応するobject渡せば良い

test.rb
User = Struct.new(:id, :name, :age)

class TestUserRepo
  def by_pk(id)
    User.new(id, "tarou", 20)
  end
end

params = { id: 1 }
user_repo = TestUserRepo.new
input = { params: params, user_repo: user_repo }

Interactor::FindUser.new(input).call

みたいにできる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0