6

単体テストのベスト プラクティスに関するこの質問では、依存性注入のためのクラスの設計について言及しています。これは一体何を意味するのだろうと考えさせられました。

コントロール コンテナーの反転の作業を開始したばかりで、この問題についていくつかのアイデアがあるので、それらを壁にぶつけて何がくっつくか見てみましょう。

私の見方では、オブジェクトが持つことができる依存関係には 3 つの基本的なタイプがあります。

  1. オブジェクトの依存関係- 問題のクラスによって使用される実際のオブジェクト。たとえば、LogInFormController の LogInVerifier です。これらは、コンストラクターを介して注入する必要があります。クラスが十分に高レベルで、コンストラクターでこれらのオブジェクトを 4 つ以上必要とする場合は、クラスを分割するか、少なくともファクトリ パターンを使用することを検討してください。また、インターフェイスを使用して依存関係を提供し、インターフェイスに対してコーディングすることも検討する必要があります。
  2. シンプルな設定- たとえば、しきい値やタイムアウト期間など。これらには通常、デフォルト値があり、ファクトリ パターンのビルダーを介して設定する必要があります。それらを設定するコンストラクターのオーバーロードを提供することもできます。ただし、ほとんどの場合、クライアントに明示的に設定するよう強制するべきではありません。
  3. メッセージ オブジェクト- あるクラスから別のクラスに渡されるオブジェクトで、受信クラスがビジネス ロジックに使用すると思われます。例として、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ブロック内で直接インスタンス化するだけです。当然のことながら、単体テストを作成する価値がある場合は、おそらく注入する価値があります。

それで、あなたたちはどう思いますか?追加のガイドラインや対照的な意見は大歓迎です。

4

1 に答える 1

1

重要なことは、インターフェースにコーディングして、インスタンス自体を作成するのではなく、クラスにそれらのインターフェースのインスタンスを受け入れさせることです。明らかにこれに夢中になることもありますが、単体テストやDIに関係なく、一般的には良い習慣です。

たとえば、データアクセスオブジェクトがある場合、次のようにすべてのDAOのベースを作成する傾向があります。

public class BaseDAO
{
    public BaseDAO(String connectionURL, 
                   String driverName, 
                   String username, String password)
    {
        // use them to create a connection via JDBC, e.g.
    }

    protected Connection getConnection() { return connection; }
}

ただし、インターフェイスを優先して、これをクラスから削除することをお勧めします

public interface DatabaseConnection
{
    Connection getConnection();
}

public class BaseDAO
{
    public BaseDAO(DatabaseConnection dbConnection)
    {
        this.dbConnection = dbConnection;
    }

    protected Connection getConnection() { return dbConnection.getConnection(); }
}

これで、の複数の実装を提供できますDatabaseConnection。単体テストを無視しても、JDBCを使用していると仮定するとConnection、コンテナーから接続プールを取得する方法と、ドライバーを使用して直接取得する方法の2つがあります。現在、DAOコードはどちらの戦略にも結合されていません。

MockDatabaseConnectionテストでは、コードをテストするために、既定のデータを使用して組み込みJDBC実装に接続するを作成できます。

于 2008-09-24T14:45:01.503 に答える