経緯
検索すればヒットするものの、いまいち掴みづらかったので
私なりにコンパクトにまとめてみました。
DIの概説
DI (Dependency Injection、依存の注入)とは、設計方法の一つ。
部品(クラス)同士の直接的な依存をなくし、部品をより抽象的なものに依存させる。
これによりテストしやすくなったり、部品(クラス)の変更が容易になったりする。
使用目的
- 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では、クラスを持つのはやめて、インタフェースを持たせる、という話をした。
インタフェースとは、抽象物であり、ルールであり、つまり実体がない、インタフェースは動かすことができない。
このインタフェースを満たす実体、クラスを入れることで、初めてソフトが動くようになる。
この「クラスを入れる」ということが、「注入」である。
そして注入されたものに依って、ソフトの動作は変わる。
つまり、ソフト動作は注入された「クラスに依存」することになる。
これが「依存」を「注入」しているということである。
以上
コメント