ひがやすを技術ブログ

電通国際情報サービスのプログラマ

DIって本当に必要? その4

http://d.hatena.ne.jp/higayasuo/20070417#1176813784の続き。
前回のエントリーでDIContainerが提供する機能で重要なのは

  • AOP
  • スコープ管理

で、IoCDIContainerの敷居を高くしていると書きました。それでは、どうしたらよいのでしょうか。
必要なオブジェクトは、自分から取りにいけばよいのです。たとえば、AOPとスコープ管理を低要するFactoryクラスがあるとします。


public class Factory {
public static T getInstance(Class<? extends T> type) {
...
}
}
使うときには、次のように呼び出します。

Service service = Factory.getInstance(Serivice.class);
このFactoryクラスを使ったときのClientクラスは次のようになります。

class Client {
Service service = Factory.getInstance(Serivice.class);
void setService(Service service) {
this.service = service;
}
void go() {
service.go();
}
}
Serviceクラスを使いたいと思ったら、自分からFactory.getInstance()を呼び出せばよいのです。DIの設定のためのファイルやコードも不要です。テストのときには、setService()メソッドを通じてモックを設定してあげればこれまでのDIと同様に簡単にテストすることができます。
Factory.getInstance()に依存したらPOJOじゃないじゃん。という声が聞こえてきそうです。それでは、Guice版のコードと比べてみましょう。


@Inject Service service;

  • Factory


Service service = Factory.getInstance(Serivice.class);
の二つがどれほど違うというのでしょうか。テストのしやすさという点ではどちらも一緒です。「いきすぎたPOJO信仰」がFactoryに依存するのをためらわすのです。効果は一緒なのに。
Factoryを直接呼び出すメリットは、DIの設定が不要であることだけでなく、直接newされるようなオブジェクトでもFactoryを通じて必要なオブジェクトが取得できるということです。
また、各フレームワークDIContainerにいちいち対応する必要もありません。これは、どういう意味かというと、たとえば、StrutsのActionでDIContainerで管理されているオブジェクトを使いたい場合、これまでだと、StrutsDIContainerに対応させるために、Actionが生成されるタイミングでDIContainerと連携を取るグルーコードを書く必要がありました。
しかし、Factoryを使う場合は、グルーコードは不要です。必要なときに自ら呼び出せばよいのですから。
テストのしやすさという面では、実はこれまでのDIよりもやりやすくなっています。これまでのDIでは設定ファイルなしでテストする場合、必要なプロパティをすべて手動で設定する必要があり、面倒でした。
Factoryを使う場合は、プロパティが全部設定された上で、必要なものだけモックで上書きすることができます。