Dependency Injectionについて

DI(Dependency Injection)について、あるところで聞かれたので回答したときのメモでも残します。

簡単に言うと、よく言われる「依存性の注入」といいます。

が、なんのことかさっぱりわからないですね。 少し言い換えてあげると

「依存性をモジュールもしくはクラス内部に抱え込まずに外部から依存内容を設定してあげる」

となります。

擬似コードを出すとDI前にこんなコードとすると

1
2
3
public Hoge(){
    this.fuga = new Fuga("hogefuga");
}

DI後の擬似コードはこんな感じ

1
2
3
public Hoge(Fuga fuga){
    this.fuga = fuga;
}

コンストラクタの引数Fugaを差し替えるだけで容易に設定内容を変更できます。
依存前のコードだと、依存性はFugaコンストラクタの中にありますが、依存後のコードは依存性は外部にあります。(引数の内容次第)
このFugaのコンストラクタがリソースに関わる何かだとDI前のコードであればユニットテストが大変になりますね。
しかし、DI後のコードであれば引数を差し替えるだけでユニットテストができるようになります。

なので、DIをするメリットというと(個人的に)以下が挙げられます。

  • 依存しているものが外部にあるので、ユニットテストで差し替えが簡単にできる(外部からモックにしやすい)
  • IFさえ同じものであれば、別の実装を行ったものを設定として渡してやることができる(柔軟性)

面倒になるのは、事前準備ですがメリットのほうが大きいと個人的には思ってます。
面倒な事前処理(主にコンストラクタ生成ですが)をやってくれるのがDIコンテナですね。

よく使うDIコンテナだと、有名なjavaのコンテナはこんなところですかね。

  • GoogleGuice
  • Seaser2
  • SpringFramework

自分が使うときの基準だと、以下になりますね。

  • Seaser2なプロダクト(SAStrutsとか)を使っている、もしくは使う場合は、「Seaser2」のDIコンテナ
  • Spring関係の何かを使っている、もしくは使う場合は、「SpringFramework」のDIコンテナ(尤も殆ど使ったことないです)
  • それ以外の場合なら、大体「GoogleGuice」(どこかに事例とかあればいいですし、大体がWicketとかで使います)

AndroidにもDIコンテナ(RoboguiceやDagger)あるのですが、殆ど使いませんね。
使い勝手が悪かったり、ドキュメントがなかったりなので・・・