Dependency Injectionが良い理由

Dependency Injection(DI)というオブジェクト指向言語のコーディングテクニックがある。

あるクラスAの中で他のクラスBのインスタンスを生成するのをやめて、メソッドの引数とか、Aの初期化時に引数としてインスタンスを渡そうというテクニック。

良いところ1:変更に強い

PersonalComputerというクラスを作るとして、osのバージョンがわかるos_versionというメソッドを作るとすると

def PersonalComputer
  def os_version
    Windows.new("9").version
  end
end

PersonalComputer.new.os_version
# => "version9"

となる。 これはDependency Injectionしてない例。

ここで、PCにインストールしているOSを変えたくなったとして、変えようと思っても、このPersonalComputerクラスはWindowsクラスと完全にくっついてる(依存している)ので、PersonalComputerを変更しないと変えることができない。

def PersonalComputer
  def os_version
    Ubuntu.new("15").version
  end
end

PersonalComputer.new.os_version
# => "version15"

一方でDependency Injectionしている例をあげる。

def PersonalComputer
  def initialize(os)
    @os = os
  end
  
  def os_version
    @os.version
  end
end

PersonalComputer.new(Windows.new("9")).os_version
# => "version9"
PersonalComputer.new(Ubuntu.new("15")).os_version
# => "version15"

こちらはPersonalComputerクラスを変更することなくOSだけ挿げ替えができているので、1つ目のメリットとして変更に強いというのがあげられる。

良いところ2:テストしやすい

このos_versionメソッドをテストすることを考えると DIなしの方では

def PersonalComputer
  def os_version
    v = Windows.new(version:"9", user:"John", time:"15:00:00",...).version #めんどくさい
  end
end

実はWindowsクラスの初期化が超めんどくさかったとして、PersonalComputerクラスのテストをしているはずなのに、Windowsクラスの初期化に作業時間をとられるという非効率が発生するし、テスト失敗時にPersonalComputerかWindowsかどちらが悪かったのか判断しづらい。 一方でDI版では

os = double("windows", :version => "9")
PersonalComputer.new(os).os_version

のようにスタブを使って、このテストで必要になるversionメソッドだけ設定してやった上でテストすれば、無駄な時間は取られないし、純粋なos_versionメソッドのテストになる。 よって2つ目のメリットとしてテストのしやすさがあげられる。

良いところ3:名前

Dependency Injection、略すとDIという名前がかっこいい。

私はDependency Injection(DI)を使っている・・・。
○○さん、今回はDIで解決しておきました。

よって3つ目のメリットとして名前のかっこよさがあげられる。

総じて言うといい感じ。

参考: www.amazon.co.jp