依存性注入を使用する場合、これは悪いことですか:
public function __construct($service = null)
{
if(null === $service){
$service = MyNewDefaultService()
}
$this->service = $service;
}
つまり、サービスのデフォルトのフォールバック クラス タイプを持つという概念
依存性注入を使用する場合、これは悪いことですか:
public function __construct($service = null)
{
if(null === $service){
$service = MyNewDefaultService()
}
$this->service = $service;
}
つまり、サービスのデフォルトのフォールバック クラス タイプを持つという概念
このパターンは機能しますが(実際、(アンチ)パターンにはBastard Injectionという名前が付いています)、このアプローチに関連する問題があります。
コンシューマークラスに新しい依存関係を構築することMyNewDefaultService()
で、抽象化に加えて、具体的なサービスクラスに結合します。コンパイルされた言語では、これは、消費するコードが具体的な依存関係クラスを含むjar / library / dll /アセンブリへのハードな「参照」を必要とすることも意味しますが、直接構造を省略すると、代わりにインターフェイスのみで結合できます。 。スクリプト言語では、実行時に具体的な依存関係が解決可能であることを確認する必要があります。
依存関係のライフスパン管理はMyNewDefaultService
、消費クラスのライフスパンと同じになるようにハードコーディングされています。IoCコンテナによって注入および管理されるオブジェクトの寿命は、これよりも柔軟性が高くなる可能性があります(たとえば、共有オブジェクトの注入など)。
「デフォルト」パス(つまり、when)をモックアウトできないため、テストはより複雑になりました。$service == null
そのため、ユニットテスト(注入されたパスの場合、モックされた依存関係の場合)と統合テスト(デフォルトパスの場合)を組み合わせて使用する必要があります。コードの正しさを証明します。
依存関係自体にコンストラクターインジェクションを使用する他の依存関係がある場合、デフォルトの構築パスはすぐに扱いにくくなり、IoCコンテナーが行ったであろう依存関係を解決するためのすべてのハードワークを実行する必要があるため、さらに多くの結合につながります。 、例えば
if(null === $service){
$service = MyNewDefaultService(RepoFactory.Create(LoggerFactory.Create()), ...)
}
TL; DRこのアプローチは、結合階層からIoCコンテナによって管理される緩く結合された依存性注入階層に移行する一時的な段階で役立つ場合がありますが、依存性逆転の原則の真のメリットは、コンストラクターには1つのパスしかありません。つまり、具体的な実装ではなく、すべての依存関係への抽象化を結合します。