単純な DI コードではなく、なぜ IoC コンテナが必要なのでしょうか? [closed] 質問する

単純な DI コードではなく、なぜ IoC コンテナが必要なのでしょうか? [closed] 質問する

私は使っています依存性注入しばらくの間、コンストラクタ、プロパティ、メソッドのいずれかに挿入するDIを使用してきました。制御の反転(IoC) コンテナ。しかし、読めば読むほど、IoC コンテナを使用するようにというコミュニティからのプレッシャーを感じます。

私は.NETコンテナで遊んでみました構造マップNインジェクト団結、 そしてファンクIoC コンテナーがコードにどのようなメリットをもたらし、改善するのか、まだわかりません。

また、職場でコンテナを使い始めるのも不安です。同僚の多くが理解できないコードを見ることになるからです。彼らの多くは新しい技術を学ぶことに消極的かもしれません。

IoC コンテナを使用する必要があることを私に納得させてください。職場で同僚の開発者と話すときに、これらの議論を使用するつもりです。

ベストアンサー1

うわー、ジョエルがこれを好むなんて信じられない。

var svc = new ShippingService(new ProductLocator(), 
   new PricingService(), new InventoryService(), 
   new TrackingRepository(new ConfigProvider()), 
   new Logger(new EmailLogger(new ConfigProvider())));

これについて:

var svc = IoC.Resolve<IShippingService>();

多くの人は、依存関係チェーンがネストされる可能性があることに気付いていません。そのため、手動で接続するとすぐに扱いにくくなります。ファクトリーを使用しても、コードを重複させる価値はありません。

確かに、IoC コンテナーは複雑になることがあります。しかし、この単純なケースでは、非常に簡単であることを示しました。


さて、これをさらに正当化しましょう。スマート UI にバインドしたいエンティティまたはモデル オブジェクトがいくつかあるとします。このスマート UI (ここでは Shindows Morms と呼びます) では、変更の追跡とそれに応じた UI の更新ができるように、INotifyPropertyChanged を実装する必要があります。

「よし、それほど難しくなさそうだ」と思って書き始めます。

まず、次のことから始めます。

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime CustomerSince { get; set; }
    public string Status { get; set; }
}

..そして最終的にはこうなります:

public class UglyCustomer : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            string oldValue = _firstName;
            _firstName = value;
            if(oldValue != value)
                OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            string oldValue = _lastName;
            _lastName = value;
            if(oldValue != value)
                OnPropertyChanged("LastName");
        }
    }

    private DateTime _customerSince;
    public DateTime CustomerSince
    {
        get { return _customerSince; }
        set
        {
            DateTime oldValue = _customerSince;
            _customerSince = value;
            if(oldValue != value)
                OnPropertyChanged("CustomerSince");
        }
    }

    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            string oldValue = _status;
            _status = value;
            if(oldValue != value)
                OnPropertyChanged("Status");
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var propertyChanged = PropertyChanged;

        if(propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

これはひどい配管コードです。このようなコードを手作業で書いていると、クライアントから盗んでいることになると私は主張します。もっと良い、よりスマートな作業方法があります。

「一生懸命働くのではなく、賢く働く」という言葉を聞いたことがありますか?

あなたのチームに賢い人がやって来てこう言ったと想像してください。「もっと簡単な方法があるよ」

プロパティを仮想化すれば (落ち着いてください、大した問題ではありません)、そのプロパティの動作を自動的に組み込むことができます。(これは AOP と呼ばれますが、名前については気にせず、それが何をしてくれるかに注目してください)

使用している IoC ツールに応じて、次のような操作を実行できます。

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

すると、問題のオブジェクトのすべての仮想プロパティ セッターで、手動の INotifyPropertyChanged BS がすべて自動的に生成されるようになりました。

これは魔法でしょうか?はい、そうです! このコードが機能するという事実を信頼できる場合は、プロパティをラップする難解な処理をすべて安全にスキップできます。解決すべきビジネス上の問題があります。

AOP を実行するための IoC ツールのその他の興味深い使用法:

  • 宣言型およびネストされたデータベーストランザクション
  • 宣言的かつネストされた作業単位
  • ログ記録
  • 事前/事後条件(契約による設計)

おすすめ記事