DIコンテナなんていらない

DIコンテナなんていらない。PHPのようなスクリプト言語では。


JavaでDIコンテナが必要なのは、Javaコンパイル型言語であり、かつ記述が長ったらしいという特徴があるからだ。そのため、頻繁に変更したい部分をXMLファイルに外だしする必要がある。


しかしPHPのようなスクリプト言語では、コンパイルの必要がないし、コードも簡潔に書ける。わざわざXMLファイルを用意する必要はなく、PHPファイルを設定ファイルに使えばいい。


例えば次のようなDIコンテナの設定とJavaコードがあるとする。

<component class="ClassA">
  <arg>"foo"</arg>
  <arg>123</arg>
</component>
S2Container container = S2ContainerFactory.create("dicon.xml");
InterfaceA obj = (InterfaceA)container.getComponent(InterfaceA.class);


これと同じことをPHPで書くとこうなる('<?php ?>'は省略)。

function get_componentA() {
  return new ClassA("foo", 123);
}
require_once('config.php');
$obj = get_componentA();


setter injectionやmethod injectionを使った場合も、

<component class="ClassB">
  <property name="prop1">"foo"</property>
  <property name="prop2">123</property>
</component>
<component class="ClassC">
  <initMethod name="initialize">
    <arg>"foo"</arg>
    <arg>123</arg>
  </initMethod>
</component>


PHPで書くとこうなる。

function get_componentB() {
  $obj = new ClassB();
  $obj->prop1 = "foo";
  $obj->prop2 = 123;
  return $obj;
}

function get_componentC() {
  $obj = new ClassC();
  $obj->initialize("foo", 123);
  return $obj;
}


PHPの場合、もっと極端にクラス名の設定だけで済ませることもできる(場合によりけりだが)。他のスクリプト言語でも似たようなものだろう。

// config.php
$ComponetClass = 'ClassA';
// main.php
$obj = new $ComponentClass("foo", 123);


またオブジェクトに依存関係があっても、何の問題もない。

function get_componentD() {
  $x = get_componentX();
  $y = get_componentY($x);        // $y は $x を使う
  $z = get_compomentZ($y);        // $z は $y を使う
  $obj = new ClassD($x, $y, $z);  // $obj は $x と $y と $z を使う
  return $obj;
}


こう書くとよく分かるが、DIコンテナの設定ファイルで書いてるのは、結局はオブジェクトを生成するためのコードと別に変わりない。プログラムコードがXMLになっただけで、本質は変わってない。


ここで大事なのは、PHPではPHP以外の余計な知識が一切不要だということである。これは、ツールやライブラリの学習コストがかからないことを意味する。


また、自分でいかようにもカスタマイズできる点も大事だ。例えば環境変数の値によってオブジェクトを切り替えたい場合も、PHPなら簡単にできる。

function get_componentA() {
    if ($_ENV['MODE'] == 'DEVELOPMENT') {
        return new ClassA1("foo", 123);
    } else {
	return new ClassA2("foo", 123);
    }
}


同じことをDIコンテナで行おうとしたら、DIコンテナがそのような機能を持ってないとできない。あるいは自分でDIコンテナのソースを拡張しなければならない。


DIの考え方自体はPHPでも役に立つと思うが、DIコンテナはPHPのようなスクリプト言語では必要ない。Javaで流行っているからといって、PHPにも同じものを押し付けるのは勘弁してほしい。


Javaを参考にしてもいいけど、真似する必要はない。PHPPHPのやり方でやればいい。Strutsが使われている?知らんがな。テンプレートエンジンが必要?PHPファイルでええがな。PHPPHPであってJavaではないんだから、PHPの特徴を生かすことを考えろ。