DI (Dependency Injection) 依存の注入とは

経緯

検索すればヒットするものの、いまいち掴みづらかったので
私なりにコンパクトにまとめてみました。

DIの概説

DI (Dependency Injection、依存の注入)とは設計方法の一つ
部品(クラス)同士の直接的な依存をなくし、部品をより抽象的なものに依存させる。
これによりテストしやすくなったり、部品(クラス)の変更が容易になったりする。

使用目的

  • DIによって部品同士の直接的な依存をなくすことで、テストのときに、スタブやモックなどを簡単に使えるようにする
  • 部品(クラス)の変更や交換を容易にする
    など

DIの考え方

クラス(実体)に依存させるのはやめて、インタフェース(抽象、ルール)に依存させようということ。

クラスに依存するのはやめて
クラスに依存画像

インタフェースに依存させるDI画像

このように、部品(クラス)同士を直接繋ぐのをやめて、インタフェース(抽象、ルール)を介して繋ぐことで、インタフェースを満たす部品(クラス)との交換が可能となる。

具体例(コード例)

夏タイヤと冬タイヤの違いによる、車の走行性能テストを行う
走行性能は、装備するタイヤに依存する。
もし、DIにせずに、車クラスに夏タイヤをそのまま持たせるとすると、走行テストは以下のようなコードになる。

class 冬タイヤ{}
class 夏タイヤ{}

class 車
{
    夏タイヤ tire;   //車は夏タイヤを持つ

    public 車(){    //コンストラクタ
        夏タイヤ tire = new 夏タイヤ();
    }
    public void 運転(){}
}

void 走行テスト(){
    車 car = new 車();
    car.運転();
}

さて、同じ車で冬タイヤのテストはどう行えばよいだろうか?
作成した車クラスは、夏タイヤクラスに依存してしまっている。
これでは、車クラスを変更しなければ冬タイヤのテストが実施できない。

次に、これをDIを用いて書いてみよう。

interface ITire {}
class 冬タイヤ implements ITire {}   //ITireインタフェースを実装
class 夏タイヤ implements ITire {}   //ITireインタフェースを実装

class 車
{
    ITire tire; //車はITireを持つ

    public 車(ITire t){    //コンストラクタ
        tire = t;
    }
    public void 運転(){}
}

void 走行テスト夏(){
    車 car = new 車(new 夏タイヤ());    //夏タイヤを注入
    car.運転();
}
void 走行テスト冬(){
    車 car = new 車(new 冬タイヤ());    //冬タイヤを注入
    car.運転();
}

無事、車クラスを変更することなく、夏と冬のテストを実施することができた。

Dependency Injection「依存の注入」とは
つまりどういう意味か

DIでは、クラスを持つのはやめて、インタフェースを持たせる、という話をした。
インタフェースとは、抽象物であり、ルールであり、つまり実体がない、インタフェースは動かすことができない。
このインタフェースを満たす実体、クラスを入れることで、初めてソフトが動くようになる。
この「クラスを入れる」ということが、「注入」である。
そして注入されたものに依って、ソフトの動作は変わる。
つまり、ソフト動作は注入された「クラスに依存」することになる。
これが「依存」を「注入」しているということである。

 

以上

コメント

タイトルとURLをコピーしました