DI(Dependency Injection)もしくはIoC(Inversion of Control)と呼ばれるアーキテクチャが注目を集めている。前回紹介したAvalonプロジェクトには,MerlinというIoCコンポーネント・コンテナが提供されている。Avalonプロジェクト自体,コンポーネント指向のサーバー・サイド・アプリケーションを作成するためのプロジェクトである。それゆえ,MerlinはAvalonプロジェクトの中心にあるものと言ってもよいだろう。

Merlinのコンポーネントは普通のクラス

 EJBコンテナがEJBを管理するように,Merlinはコンポーネントを管理するコンテナである。ここでいうコンポーネントとは,EJBのような特殊なものではない。

 Merlinが扱うコンポーネントは機能であるサービスを提供する普通のクラス,言い換えればPOJO(Plain Old Java Object)で作成されたクラスである。コンポーネントは複数のクラスや他のコンポーネントを利用してサービスを提供するように作成されていても構わない。むしろそのほうが多いだろう。各コンポーネント同士は疎結合となるように作成し,それらを組み合わせてアプリケーションを作成してゆく。この方法コンポーネント指向と呼ぶ。

 ただし,コンポーネントが自身のサービスを完了するために別のコンポーネントを必要とする場合もあるだろう。そのような場合,別のコンポーネント(依存コンポーネントと呼ぶ)を内部で生成するのではなく,外部から受け取るようにする。この考え方が前述したDependency Injectionパターン,別の呼び方をすればInversion of Controlである。

 各コンポーネントには必ずインタフェースを作成する。プログラムからはすべてインタフェースを通して,コンポーネントにアクセスする。前述のDependency Injectionも,そのインタフェースでコンポーネントを参照するように記述する。このように,オブジェクトの実装とインタフェースを分離して実装を隠蔽することで,オブジェクトの変更や置き換えが容易となる。アプリケーションとしての拡張性を確保すると同時に単体テストも容易に行えるようになる。

 さらに,Merlinを含めた多くのコンポーネント・コンテナは,コンポーネントのインスタンス生成機能も提供している。そのため依存するコンポーネントのインスタンスの生成のタイミングをプログラム中で記述する必要がない。それらは設定ファイルによって定義され,必要な時にコンテナが自動的に生成する。また,各コンポーネントは必要なときにコンテナが呼び出すようになっており,開発者は実行タイミングを考慮することなくサービスのためのロジック実装に注力できるのである。

 この手法は,単体テストにおいても効果を発揮する。単体テストにおいては,単一のクラスのみをテスト対象とするはずだ。しかし多くの場合,依存するクラスのインスタンスを内部で生成してしまいがちである。複数のクラスが同時に動作してしまい(場合によっては,ビジネスロジック・クラスの単体テストを行うと,データベース・アクセスまでしてしまう)厳密な意味での単体テストが困難になる場合が多いだろう。このような場合にも,前述のようなDependency Injectionパターンを利用すればよい。注入するオブジェクトを,依存するクラスのインタフェースを実装したモック(擬似)オブジェクトを生成するようにしておくことで,依存するクラスを呼び出す事なく純粋にクラス単体のテストが行える。

 Merlinは,このような機能を提供するコンポーネント・コンテナである。その思想をよく理解し機能をうまく利用することで,コンポーネント指向のアプリケーションを簡単に作成することができるようになる。