2012年5月16日水曜日

DIを擬人化して理解してみる

Dependency Injection(DI)とか依存性の注入などと言われてもピンとこない。
仕方がないので、実験的に作っているAmidaMVCというPHPフレームワークでDIコンテナを自作してみました。

まぁDIとはこういうものかな?
というのを擬人化して説明を試みた結果です。

◆ DI以前のオブジェクトとは

あるオブジェクトが動作するため、別のオブジェクトに依存している状況を「依存性がある」と言います。依存性があること自体は問題はありませんが、
依存性が固定されている
のが問題と考えられます。

これを擬人化すると
「俺は、こいつと永遠に一緒だぜ」
となるのではないでしょうか?

コードで書くと

class foo {
  protected $love = NULL;
  function __construct() {
    $this->love = new \My\Love();
  }
}

というところでしょう。

一途というのはいいものだけれど、融通がきかない。
これを何とかするのがDIです。

◆ DI(依存性を注入する)

ようは
「誰とでもOK、注入してして」。
という軽さを売りにするのがDI。

コードにすると、

class foo {
  protected $love = NULL;
  function injectLove( $love ) {
    $this->love = $love;
  }
}

こういうのを汎用性が高いと言うのでしょう。
テストしやすい、というのがDIを正当化するのによく言われます。

ただ実際には使いづらい面があります。

◆ IoC(Inversion of Control)

何しろオブジェクトを作るには何かを注入してやらなければいけない。
独り立ちではなく、逆に誰かに依存してしまいます。

これを擬人化すると、
「一人だと何も出来ないんです。誰か注入してください」
と言う「ひ弱な僕」というのがピッタリな表現でしょう。

このように、使う方から使われる側へとオブジェクトの実装を変更することを
制御の反転(Inversion of Control)
と呼びます(多分)。

◆ Container(コンテナ)

こんなひ弱なオブジェクトたちにはママが必要です。
「あ~、坊やにはこれを注入してあげるからね」
これをコンテナと呼びます。
いろんな作り方があるけど、例えばこんな感じ?

class DiMom {
  function loveFoo() {
    $foo = new foo();
    $foo->injectLove( new \I\Love\You() );
    return $foo;
  }
}
オブジェクトの生成を一手に担い、適切なオブジェクトを注入して依存性を解決してあげる。そんなBig Motherのようなクラスをコンテナと呼ぶのでしょう。

実際には、コードでゴリゴリ書くのではなく設定できるようにすると思いますが。


◆ Service Locator(SL)

以上、色々書きましたが、未だにSLとコンテナの違いがよく分かってません。似ているようで違う、というか、多分自分の書いたコンテナはSLの事な気がしています。いや、何が違うのだろう?

思うに、オブジェクトがコンテナに依存している状態をSLと呼ぶのではないでしょうか?

自分が開発しているフレームワークはChain of Responsibilityを使っていて、必要に応じてモジュール(オブジェクトのことです)を呼び出します。
正確に言うと、ある処理を行うのに必要なモジュールを判断するモジュールがあって、そのモジュールがチェーンに必要なモジュールを追加します。
フレームワークは順番にオブジェクトを生成・実行するだけですが、生成部分にコンテナを使いますが、これだと多分SLという区分になる気がします。

また理解できたと思ったら書いてみます。


◆ 参考文献

色々読んだけど、今ブックマークしてあるもののみリスト。


0 件のコメント: