一般に、ユニットテストに関して「新しい」オペレーターについて考える方法で概説されている理由で、私はDI群衆とチャイムを鳴らします。
しかし、依存性注入が非常に重要である理由は、単体テスト内でアプリケーションの小さなサブセットをテストしたいからです。要件は、システム全体から独立して、アプリケーションのその小さなサブセットを構築できることです。アプリケーションロジックとグラフ構築(新しい演算子)を組み合わせると、アプリケーションのリーフノード以外では単体テストが不可能になります。
コードをクリエーターグラフとコラボレーターグラフに分けると、コードの保守とテストが可能になります。さらに良いことに、インターフェースに対するコードを作成すると、具体的な実装を他の実装と交換するのが非常に簡単になります。これにより、ハードコードされた依存関係を探すためにコードを探す必要がなくなるため、コードの変更が簡単になります。
たとえばBar
、ロガーが必要だとすると、
class Foo
{
private $logger;
public function __construct(LogInterface $logger)
{
$this->logger = $logger;
}
}
LogInterface
次に、データベースロガー、StdOutLogger、またはこれらの両方を保持する複合ロガーなど、それを実装する具体的な実装を渡します。もう1つの例は、Databaseオブジェクトです。ブートストラップで一度作成し、それを使用してオブジェクトに渡すことができます。
疑わしい場合は、依存性注入を使用してください。
ただし、必ずしも何かを注入する必要はありません。オブジェクト(バー)がInjectableであるかNewableであるかによって異なります。Misko Heveryを引用するには:
Injectableクラスは、コンストラクターで他のInjectableを要求できます。[…]注射剤は、テストに適した実装に置き換える必要がある可能性があるため、インターフェイスを持つ傾向があります。ただし、Injectableは、コンストラクターでInjectable以外(Newable)を要求することはできません。これは、DIフレームワークがNewableを生成する方法を知らないためです。[…]Newablesの例としては、Eメール、MailMessage、ユーザー、クレジットカード、歌などがあります。この区別を維持すると、コードのテストと操作が簡単になります。このルールに違反すると、コードのテストが困難になります。
一言で言えば、ユーザー提供または実行時の情報に基づいているため、合理的に注入できないものがある場合は、それを実行できnew
ます。これは、値オブジェクトとデータ型に特に当てはまります。
class Foo
{
private $storage;
public function __construct()
{
$this->storage = new SplObjectStorage;
}
}
注入しても意味がありませんSplObjectStorage
。これは単なるデータ型です。