Moduleは高速で副作用がないほうがよい
Guiceのモジュールは、設定にXMLファイルではなく、Javaコードを使用する。Javaは親しみやすく、IDEの機能を活用でき、リファクタリングにも対応できる。
しかし、Javaの力はコストももたらす。つまり、Moduleでやりすぎてしまうのだ。GuiceのModuleでは、データベースへ接続し、HTTPサーバーを起動することもできる。ダメだ!Moduleで困難な仕事をすると、問題が発生する。
- Moduleは起動するが、終了しない ― データベース接続を開いたとき、その接続を閉じるフックはない
- Moduleはテストされるべき ― 実行時にデータベースへ接続すると、単体テストが難しくなる
- Moduleはオーバーライドできる ― GuiceのModuleはオーバーライドをサポートしており、製品版とテスト版や軽量版と置換えができる。製品版の機能がモジュール実行の一部として実装されたとき、そのようなオーバーライドは効果がない。
Module自身で実行するよりも、適切な抽象レベルのインターフェイスを定義する。アプリケーションでは、このようなインターフェイスを使用できる。
public interface Service {
/**
* Starts the service. This method blocks until the service has completely started.
*/
void start() throws Exception;
/**
* Stops the service. This method blocks until the service has completely shut down.
*/
void stop();
}
Injectorを生成した後でServiceを開始し、アプリケーションの起動を完了する。また、アプリケーションが停止したときに、リソースを解放するシャットダウンフックを追加する。
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(
new DatabaseModule(),
new WebserverModule(),
...
);
Service databaseConnectionPool = injector.getInstance(
Key.get(Service.class, DatabaseService.class));
databaseConnectionPool.start();
addShutdownHook(databaseConnectionPool);
Service webserver = injector.getInstance(
Key.get(Service.class, WebserverService.class));
webserver.start();
addShutdownHook(webserver);
}
参照
Modules should be fast and side-effect free