依存性注入(DI)と制御の反転(IoC)コンテナーを使用したコンポジションルートの許容可能な配置


8

Mark Seemannの 'Ploeh'ブログを含むいくつかのソースで、IoCコンテナーのコンポジションルートの適切な配置がアプリケーションのエントリポイントに可能な限り近いことについて読んだことがあります。

.NETの世界では、これらのアプリケーションは、一般的にWebプロジェクト、WPFプロジェクト、コンソールアプリケーション、一般的なUIを持つもの(読み取り:ライブラリプロジェクトではない)と考えられているようです。

構成ルートをライブラリプロジェクトのグループの論理的なエントリポイントを表し、このようなプロジェクトグループのクライアントが他の誰かの作業である場合、構成ルートをライブラリプロジェクトのエントリポイントに配置することは、この賢明なアドバイスに本当に反していますか? 、その作者が自分のプロジェクト(UIプロジェクトまたはさらに別のライブラリプロジェクトでさえ)にコンポジションルートを追加できない、または追加しないだろう?

私はIoCコンテナー実装としてNinjectに精通していますが、必要なすべてのバインディング構成を含むモジュールをスキャンできるという点で、他の多くも同じように機能すると思います。これは、バインディングモジュールを独自のライブラリプロジェクトに配置して、メインライブラリプロジェクトの出力でコンパイルできることを意味します。クライアントが構成を変更したい場合(私のケースではありえないシナリオ)、置換DLLをドロップして、バインディングモジュールを含むライブラリ。

これにより、最も一般的なクライアントが依存関係の注入とコンポジションのルートを処理する必要がなくなり、ライブラリプロジェクトグループのAPIが最もクリーンになります。

しかし、これはこの問題に関する従来の知恵に直面して飛んでいるようです。そこにあるほとんどのアドバイスは、開発者が自分のケースではなく、UIプロジェクトの開発にも何らかの調整を行っていることを前提としているだけですか?

回答:


2

あなたのバインディングモジュールアプローチは最良のソリューションです。クライアントが構成を変更する可能性が低い場合は、特にライブラリのDIの使用に問題があります。

一般向けにリリースするライブラリを作成する場合、クライアントが現時点で好む特定のDIシステムの複雑さや厳格さを処理することは望ましくありません。ライブラリは、多くの依存関係や広範なトレーニングなしで使用できる下位レベルのコンポーネントである場合に最適です。選択したDIシステムは時間とともに変化し、クライアントアプリケーションとの互換性がなくなる可能性があります。


2

ライブラリは、クリーンなドメイン固有のAPIを備えたブラックボックスであると想定されています。クライアントにリークせず、何らかの方法でクライアントを制約しない限り、DIを含むライブラリ内で必要なツールやパターンを使用しても問題はありません。

拡張性またはライブラリ構成の変更を提供する必要がある場合でも、ライブラリとクライアント間で単一のコンポジションルートを共有しなくても実行できます。

ライブラリにDIを実装するためだけに別のサードパーティライブラリに依存してライブラリを正当化できるかどうかは別の問題ですが、DIパターン自体は依存関係なしで実装できることに注意してください。


-1

他の人が使用するための(アプリケーションではなく)ライブラリを開発している場合でも、依存関係の注入を実装する必要があります。私にとって「依存性注入」という用語は、懸念の分離と疎結合につながる一連のプラクティスにすぎません。これにより、ライブラリが適切に構造化され、テストが容易になります(ほとんどの場合)。

IoCコンテナに関しては、ライブラリプロジェクトにIoCコンテナを配置しても害はありません。どこかに、ライブラリへのコンポジションルート(エントリポイント)があるので、コンポジションルートで依存関係を結び付けるのは完全に理にかなっています。方法は完全にあなた次第です。

例として、私は最近、署名をキャプチャするためのライブラリとバーコードをスキャンするためのライブラリを使用しました。どちらもシンプルな相互運用ライブラリ(COMラッパー)でした。各ライブラリでは、何をする前に初期化する必要がありました。例えば:

var isReady = _signatureCapture.Initialise()
if (isReady)
{
   // Do stuff
}

バーコードスキャンライブラリは非常に似ていました。

_scanner.Initialise();
_scanner.OnScan += OnScanHandler;

私は両方のライブラリを使用しており、IoCコンテナを使用するかどうかはわかりません。ただし、ライブラリへのエントリポイントがInitialiseメソッド内にあることは知っています。私はすべての依存関係がInitialiseメソッドで関連付けられていると思います。これは、コンポジションルートとして機能します。

サードパーティのIoCコンテナーに依存することを心配している場合は、独自の非常に単純化された実装でロールすることができます。開発者はライブラリが古くなったり、より良いものに取って代わられたりすることを心配することがよくありますが、実際には、チームが1つのIoCコンテナーを別のIoCコンテナーに交換することにしたプロジェクトはまだ見ていません。


4
ライブラリは、不要な依存関係を回避する必要があります。アプリケーションのように非常に複雑なライブラリの場合を除いて、ほとんどのライブラリユーザーは特定のDI実装への依存を望まないでしょう。
フランクヒルマン、2014年

-2

外部ライブラリーの優れている点は、シンプルでシンプルなインターフェースを公開しながら、彼らがやろうとしていることを何でも実行できることです。実際にそれを行うのがどれほど複雑であっても、それを実装する開発者の仕事であってはなりません。DIが実際にAPI開発者の作業をそれほど複雑にしない場合、それが適切に使用され、そのモジュールがAPIのエントリポイントで宣言されている限り、それを使用することは100%意味があります。最近のMVCアプリの開発では、リポジトリパターンを使用してデータレイヤーを抽象化し、サービスレイヤーをMVCアプリとリポジトリレイヤーの間に配置することでさらに抽象化しました。どちらもクラスライブラリプロジェクトです。サービスコンテキストのキャッシュクラスにマップされたICacheインターフェイスがありました。最初はMVC.Web.Cacheを使用して実装しましたが、後でIterationでSystem.runtimeにスワップしました。キャッシュを使用すると、DIを使用しないと、リファクタリングの規模がどれだけ大きいか想​​像できます。だから私のアドバイス; "頑張れ"。


この投稿は読みにくいです(テキストの壁)。より良い形に編集していただけませんか?
gnat 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.