DIコンテナってどうよ!?

と、ちょっと前から考えていました。効果ある?みたいな。DIが騒がれて2年くらい経つのかな。自分のプロジェクトでもいち早く導入したものの開発効率が上がったり、コード数が減った、テストしやすくなった、バグが減った、などの劇的な効果が何も出ていない。むしろほとんど使っていない。。。なーんでか、ということを考えてみた。

最大の欠点 -生成に関する問題-

オブジェクト指向分析・設計の結果としてドメインモデルを作成した場合、データとビジネスロジックを持ち、データを持つが故に永続化対象となることがほとんどだと思います。ドメインモデルは単にnewしてもほとんど意味がありません。「状態」がないんだから。なので、通常はDBからデータを取ってきて、それらのデータが格納された状態で初めて意味があります。
でもそのようなオブジェクトはDIコンテナからは生成できません。DIコンテナが生成できるのはnew可能なもの、つまり「状態」を持たないオブジェクトです。ここが自分のプロジェクト(もろオブジェクト指向モデリング)で使えなかった最大の欠点だと思います。

世間ではどうしてるんだ?

じゃ、DIコンテナをベースにしたアプリケーションってどんなんだろう?と思っていたのですが、シーサーサンプルプロジェクトの上級にある、家計簿Webアプリをダウンロードしてコードを見ることで、理解することが出来たと思います。
レイヤは次のようになっています。

StrutsAction→Service→DAO

Serviceとは何かというと、ビジネスロジックを担当するオブジェクトですが、こいつは「状態」を持ちません。DAOよりDBアクセスしてDTOを得て、それを利用するだけ。この場合、StrutsActionは通常DIでは管理できない領域ですが、S2Strutsを使っているので、DIコンテナが管理するコンポーネントとして利用できます。StrutsActionはServiceを持ち、Serviceは必要なDAOを持つ。その設定が行われているので、StrutsActionの実行に来た段階でServiceなどが注入されている、というわけ。
オブジェクト指向信者からすると、Serviceクラスはただの関数クラスですから、この構成に違和感を覚えると思います。Serviceではなく、ドメインモデルにそのロジックを持っていきたくなると思いますが、そうしちゃうとDI使えなくなるよ、と。

どっちに行く?

ではどっちのスタイルがいいか。なーんて話をしたら尽きない議論になりそうなので、是非を問うのはやめる。どちらも良い点、悪い点があると思うので。使い分けのポイントは再利用の範囲ではないかと。SIなんかでお客様固有の案件を行う業務アプリの場合は再利用性なんか考えなくてもいい訳なんで、DI方式でもいいと思います。むしろこっちの方がデータモデリングを行えば、あとはお客様の仕様を満たす関数を作っていけばいいので、いい気がする。変にオブジェクト指向が...云々なんて議論してたら変に凝って失敗しそう。
ただ複数のWebアプリケーションで共通して利用するビジネスロジックがあったとして、そのビジネスロジック部分を作るのであれば、オブジェクト指向方式がいいと思います。DAOを提供するってのも変だし、関数を提供してもなぁと。ドメインモデルのオブジェクトたちのメソッドをAPI提供した方が使いやすいだろうし。フレームワークっぽい要素も含むことがあるので、変更に強いか、なども考えたいし。

疑問

とまぁ、一応自分の中で結論付けましたが、これだとオブジェクト指向とDIが相性悪いみたいで。。それはそれでなんか間違っているようでひっかかりますなぁ。オブジェクト指向と相性が悪いというか、永続化したものと相性が悪い。。うーん、やっぱなんか間違ってる気もする。
あと、AOPの使用にしても、DIコンテナで管理しているコンポーネントだけに限られるのってどうなんでしょ。微妙に使いづらいような。AspectJなんかを使えばそんな足枷無いわけだし。

おまけ

このエントリーを書いた後で発見。タイムリーにもひがやすをさんのblogで「DIって本当に必要?」というエントリーがありました。
そうそう、Factoryで十分じゃん!という時ありますよね。これだけDIが叫ばれると、いまどきFactory作るのってどうよ!?ってなるけど、ハヤリにだまされてはいけませんね。
ただ、ひがさんの言うDIコンテナのメリットである

  • AOP
  • スコープ管理

はどうでしょう。AOPは上で言った疑問があります。スコープ管理も、、ちょっとは楽かな、くらいにしか今は思えません。