Hatena::Groupcatalyst

dann@catalyst このページをアンテナに追加 RSSフィード

2008-04-02

Dependency Injection

00:09 |  Dependency Injection - dann@catalyst を含むブックマーク はてなブックマーク -  Dependency Injection - dann@catalyst  Dependency Injection - dann@catalyst のブックマークコメント

外部から依存関係を挿入する。ただ、それだけのことです。

Dependency Injectionのパターンを使うことで何が嬉しくなるのか?

依存関係が挿入されるため、依存するオブジェクトの詳細が、その依存関係を挿入されるクラスから切り離されます。要するに、単体テストが簡単になるということです。

では、具体的な例を見てみましょう。

MyApplicationが何らかのLoggerに依存していたとします。仮にLoggerが以下のように依存関係があったとします。

package MyApplication;
use Moose;

sub run {
    my $self = shift;
    my $logger = FileLogger->new(log_file_name => 'hoge.log');
    $logger->log();
}

1;

このように依存関係がハードコードされている場合、FileLoggerを違うLoggerに変えてテストをすることが難しくなってしまいます。例えば、依存先がDBに依存していたりすれば、DBなくしてはテストができなくなってしまいます(Monkey Pachingで回避できないことはないですが)

では、どうすれば、MyApplicationからこのloggerの実装への依存を断ち切れるでしょうか。こんなときに依存関係を断ち切るために使われるのが、Dependency Injection(IoCパターン)です。

以下のようにします。要するに、loggerの依存関係をMyApplicationの外に出してしまいます。MyApplicationに任意のLoggerを設定すれば、MyApplicationは任意のLoggerでrunメソッドを実行できるようになります。外からLoggerへの依存関係を注入することになるので、Dependency Injectionといわれています。

Dependency Injectionそのものは、とてもシンプルなアイデアですが、Testabilityを高めるための重要なテクニックの一つです。他にも依存関係を切る方法はあるのですが、ここではDependency Injectionのパターンだけを紹介することにします。

package MyApplication;
use Moose;
has 'logger' => (is =>'ro', required => 1);

sub run {
    my $self = shift;
    $self->logger->log();
}

1;

では、このDependencyは誰がInjectしてくれるのでしょうか。もっと簡単に言えば、誰がMyApplicationのコンストラクタに、FileLoggerというLoggerの実装のインスタンスを設定してくれるのでしょうか。

そこで出てくるのがDIコンテナです。手動でFileLoggerをnewして設定する方法もありますが、それだとMyApplicationを利用するクラスが実装に依存してしまうことになります。結局それはテスタビリティを損なうことになるかもしれません。

MccadeMccade2011/08/02 12:38This forum needed sakhing up and you've just done that. Great post!

kmeyilypzkmeyilypz2011/08/03 20:4915ggJ4 , [url=http://qeznvwezdxfs.com/]qeznvwezdxfs[/url], [link=http://nuwhqfxgeivl.com/]nuwhqfxgeivl[/link], http://srnfyjntrpcw.com/

hvqabaqxdhvqabaqxd2011/08/05 22:13fSEfDn , [url=http://hitejlqemnsf.com/]hitejlqemnsf[/url], [link=http://ldrpnarvjijm.com/]ldrpnarvjijm[/link], http://mvfzvlgrqjjn.com/