単体テストのベスト プラクティスに関するこの質問では、依存性注入のためのクラスの設計について言及しています。これは一体何を意味するのだろうと考えさせられました。
コントロール コンテナーの反転の作業を開始したばかりで、この問題についていくつかのアイデアがあるので、それらを壁にぶつけて何がくっつくか見てみましょう。
私の見方では、オブジェクトが持つことができる依存関係には 3 つの基本的なタイプがあります。
- オブジェクトの依存関係- 問題のクラスによって使用される実際のオブジェクト。たとえば、LogInFormController の LogInVerifier です。これらは、コンストラクターを介して注入する必要があります。クラスが十分に高レベルで、コンストラクターでこれらのオブジェクトを 4 つ以上必要とする場合は、クラスを分割するか、少なくともファクトリ パターンを使用することを検討してください。また、インターフェイスを使用して依存関係を提供し、インターフェイスに対してコーディングすることも検討する必要があります。
- シンプルな設定- たとえば、しきい値やタイムアウト期間など。これらには通常、デフォルト値があり、ファクトリ パターンのビルダーを介して設定する必要があります。それらを設定するコンストラクターのオーバーロードを提供することもできます。ただし、ほとんどの場合、クライアントに明示的に設定するよう強制するべきではありません。
- メッセージ オブジェクト- あるクラスから別のクラスに渡されるオブジェクトで、受信クラスがビジネス ロジックに使用すると思われます。例として、LogInCompleRouter クラスの User オブジェクトがあります。ここでは、多くの場合、コンストラクターでメッセージを指定しない方が良いことがわかります。これは、User インスタンスを IoC コンテナーに登録する (グローバルにする) か、User のインスタンスが作成されるまで LogInCompleteRouter をインスタンス化しない必要があるためです。 (DIを使用できなかったか、少なくともコンテナへの明示的な依存関係が必要になる場合)。この場合、メソッド呼び出しに必要な場合にのみメッセージ オブジェクトを渡す方がよいでしょう (つまり、 LoginInCompleteRouter.Route(User u); )。
また、すべてを DI する必要はないことにも言及しておく必要があります。使い捨てクラスに分解するのに便利な単純な機能がある場合は、その場でインスタンス化しても問題ないでしょう。明らかに、これは判断の呼びかけです。次のようなクラスを書くのが適切だとわかった場合
class PasswordEqualsVerifier {
public bool Check(string input, string actual) { return input===actual;}
}
私はおそらく依存関係を注入することを気にせず、オブジェクトをusingブロック内で直接インスタンス化するだけです。当然のことながら、単体テストを作成する価値がある場合は、おそらく注入する価値があります。
それで、あなたたちはどう思いますか?追加のガイドラインや対照的な意見は大歓迎です。