web-dev-qa-db-ja.com

IoCコンテナは、依存性注入を使用するアプリケーションの設計に影響しますか?

Containerは、DIを介してIoCを管理する「プログラム」またはメカニズムであると言っても差し支えありませんが、そうではありません。疎結合を実現するために、DIの初期設計を本当に変更しますか?

言い換えると、たとえばロガーのように疎結合を実現したい場合、コンテナーを使用してもそれは変わりません。クラスを構築するための依存関係がたくさんある場合に備えて、それを管理するだけです(入力が少なく、管理しやすく、単体テストが優れているなど)。

たとえば、ILoggerまたはIDatabaseとのインターフェイスとコントラクトがあるという事実は変わりませんか?

//Assume I have to interfaces and two classes that implement them
Class DemoDI
{
    ILogger myLogger;
    IDatabase myDatabase;

    DemoDI(ILogger myLogger, IDatabase myDatabase)
    {
        this.myLogger = myLogger;
        this.myDatabase = myDatabase;
    }

    //Methods that do stuff with the logger and database
}

それが変わらないか、そのデザインパターンを聞いています。それはどこかで(メイン?)、私は(Unityで言う)

ioc.RegisterType<ILogger MyLoggingClass>(new ContainerControlledLifetimeManager());
ioc.RegisterType<IDatabase MySQLDatabaseClass>; //transient by default

そして、MySQLDatabaseClassが持っていた場合、

interface IDatabaseConnection
{
    void GetConnection();
}
Class DataConnection : IDatabaseConnection
{

    public void GetConnection()
    {
        //Get a connection
    }

}
Class MySQLDatabaseClass
{
    DataConnection myConn;

    MySQLDatabaseClass(DataConnection myConn)
    {
        this.myConn = myConn;
        this.myConn.GetConnection();
    }
    //Do other things;


}

次に、コンテナはそれを配線します。

ioc.RegisterType<IDatabaseConnection, DataConnection>();

そうでなければ、私はそれをすべて手作業でしなければならないでしょう。 containerは、それをすっきりと整え、すべてを組み立てるヘルパーです。

ここで、データベースクラスの単体テストを行う場合は、コンテナーを調整する必要があります。

ioc.RegisterType<IDatabase MyMockedUpMySQLDatabaseClass>; //transient by default

IoCコンテナの目的を正しく理解していますか?うまくいけば、私は自分の依存関係にあまり迷わなかった。

4
johnny

コンテナはDIを介してIoCを管理する「プログラム」またはメカニズムであると言っても差し支えありませんが、疎結合を実現するためにDIの初期設計を実際に変更することはありませんか?

IoC および [〜#〜] di [〜#〜] は、以前はそれらに従わなかったデザインを変更します。コンテナを使用してもデザインは変更されませんが、多くの場合変更されます。一部のコンテナでは、コードベース全体にコンテナの知識を広める必要があります。依存関係の1つのセットを別のセットと交換することになります。クラスを見て、どのコンテナが関係しているかを知ることができないはずです。可能であれば、今はそのコンテナに依存しています。

IoCとDIは管理コンテナを必要としません。コンテナがあなたの考えをすることを期待するのではなく、それらが何であるかを理解することによって、それらを最もよく管理することができます。コンテナで管理できますが、それはあなたの選択です。

Foo foo = new Foo( new Bar() );

その権利には依存性注入があります。 FooはBar、または少なくともある種のBarのようなものに依存します。 Fooはそれなしでは存在できません。バーは依存関係です。 BarはFooに渡されているため、Barは注入された依存関係です。

IoCは、複雑な言い方です。実装に関する知識をハードコーディングしないでください。 Fooが独自のBarを構築した場合、FooはBarにハードコーディングされ、Fooは新しい種類のBarを受け入れることができませんでしたが、FooがBarについて知らない場合は、インターフェイスだけで、Fooに触れることなくBarを変更できます。

依存関係をハードコーディングしない方法はたくさんあります(IoCに従ってください)。

  • ファクトリパターン
  • サービスロケーターパターン
  • 依存性注入、
  • コンストラクター注入
  • パラメータインジェクション
  • セッターインジェクション
  • インターフェース注入
  • コンテキスト化されたルックアップ
  • テンプレートメソッドデザインパターン
  • 戦略デザインパターン

このようなことはコンテナで行うことができます。構築コードでそれを行うことができます。あなたはメインでそれを行うことができます。

どこで行う場合でも、この構築コードと動作コードを混在させないでください。ハードワイヤリングは、そもそもこの誇張されたコンテナの動きを開始した混乱を引き起こしていると感じた瞬間に詰め込まれます。それは本当の問題です。最善の解決策は、自分で修正できることを理解することです。

6
candied_orange