Beni IoC kaplarında sat, lütfen


17

Birkaç kod IoC kapları kullanmanızı tavsiye gördüm. Motivasyon basit. Aşağıdaki bağımlılık enjekte edilen kodu alın:

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest(
        std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
    ) : d_(d)
    {
    }
};


TEST(UnitUnderTest, Example)
{
    std::auto_ptr<Dependency> dep(new MockDependency);
    UnitUnderTest uut(dep);
    //Test here
}

İçine:

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest()
    {
        d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
    }
};


TEST(UnitUnderTest, Example)
{
    UnitUnderTest uut;
    //Test here
}

//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>

//Config for IOC container for testing
<Dependency>MockDependency</Dependency>

(Yukarıdaki varsayım elbette varsayımsal C ++ örneğidir)

Bunun bağımlılık yapıcı parametresini kaldırarak sınıfın arayüzünü basitleştirdiğini kabul etsem de, tedavinin birkaç nedenden dolayı hastalıktan daha kötü olduğunu düşünüyorum. İlk olarak, bu benim için büyük bir program, bu da programınızı harici bir yapılandırma dosyasına bağımlı kılıyor. Tek bir ikili konuşlandırmaya ihtiyacınız varsa, bu tür kapsayıcılar kullanamazsınız. İkinci sorun, API'nin artık zayıf ve daha kötü, dize olarak yazılmış olmasıdır. Kanıt (bu varsayımsal örnekte), IoC kapsayıcısına ve sonuçtaki oyuncuya yönelik dize argümanıdır.

Yani .. bu tür kapları kullanmanın başka yararları var mı ya da sadece kapları önerenlere katılmıyorum mu?


1
Örnek kod, bir IoC uygulamasının gerçekten kötü bir örneğine benziyor. Ben sadece C # aşina değilim ama kesinlikle yapıcı enjeksiyon ve C ++ da programatik yapılandırma için bir yolu var mı?
rmac

Yanıtlar:


12

Birçok katman ve çok sayıda hareketli parça içeren büyük bir uygulamada, avantajlara kıyasla oldukça küçük görünmeye başlayan dezavantajlar.

Kap, sınıfın "arabirimini basitleştirir", ancak bunu çok önemli bir şekilde yapar. Kap, bağımlılık enjeksiyonunun yarattığı, bağımlılıkları biryere, nesne grafikleri ve fonksiyonel alanlar boyunca geçirme sorununa bir çözümdür. Burada bir küçük örnek olması olan bir bağımlılık - bu nesne üç bağımlılıkları ve bağlı birden çok nesneyi vardı bağlıydı nesneleri ne vardı eğer onları üzerinde ve böylece? Bir kap olmadan, bu bağımlılık zincirlerinin üstündeki nesneler, tüm uygulamadaki tüm bağımlılıkları takip etmekten sorumlu hale gelir.

Farklı konteyner çeşitleri de vardır. Hepsi dizgi ile yazılmıyor ve hepsi yapılandırma dosyaları gerektirmiyor.


3
Ancak büyük bir proje, daha önce bahsettiğim sorunları daha da kötüleştiriyor . Proje büyükse, yapılandırma dosyası büyük bir bağımlılık mıknatısı haline gelir ve bir tipo'nun çalışma zamanında tanımlanmamış davranışa yol açması daha da kolaylaşır. (örneğin, yapılandırma dosyasında bir yazım hatası olması, türün yanlış türde döndürülmesi durumunda tanımsız davranışa neden olur). Bağımlılık bağımlılıklarına gelince, bunlar burada önemli değil. Yapıcı bunları yapmaya özen gösterir veya test üst düzey bağımlılığı alay eder.
Billy ONeal

... Devam ... Program test edilmediğinde, varsayılan somut bağımlılık her adımda somutlaşır. Başka tür konteynerler, bazı örnekleriniz var mı?
Billy ONeal

4
TBH DI uygulamaları ile tonlarca deneyimim yok, ancak .NET'te MEF'e bir göz atın, ancak yazılabilecek ancak dize yazmak zorunda değilsiniz, yapılandırma dosyası yok ve arayüzlerin somut uygulamaları "kayıtlı" sınıfların kendisinde. BTW, "yapıcı onları yapmakla ilgilenir" derken - yaptığınız şey buysa ("zavallı adamın yapıcı enjeksiyonu" olarak da bilinir), o zaman bir kaba ihtiyacınız yoktur. Bunun yerine bir kabın avantajı, kabın tüm bu bağımlılıklar hakkındaki bilgileri merkezileştirmesidir.
nlawalker

Bu son yorum için +1 - son cümle cevabı var :)
Billy ONeal

1
Bütün mesele bana yardımcı olan harika bir cevap. Mesele sadece kazan plakasını basitleştirmekle kalmıyor, aynı zamanda bağımlılık zincirinin üstündeki öğelerin, alttaki elemanlar gibi naif olmasına izin veriyor.
Christopher Berman

4

Java'nın Guice IoC çerçevesi bir yapılandırma dosyasına değil, yapılandırma koduna bağlıdır . Bu, yapılandırmanın gerçek uygulamanızı oluşturan koddan farklı bir kod olmadığı ve yeniden düzenlenebilir vb. Anlamına gelir.

Guice'in nihayet yapılandırmayı doğru yapan Java IoC çerçevesi olduğuna inanıyorum.


C ++ için benzer örnekler var mı?
Billy ONeal

@Billy, söyleyebilmek için C ++ 'a yeterince aşina değilim.

0

Bu harika SO cevap tarafından Ben Scheirman C # bazı kod örnekleri ayrıntıları; IoC konteynerlerinin (DI) bazı avantajları:

  • Bağımlılık zinciriniz iç içe geçebilir ve bunları manuel olarak bağlamak hızlı bir şekilde gereksiz hale gelir.
  • Kullanılmasını sağlar Aspect yönelimli programlama .
  • Bildirici ve iç içe veritabanı işlemleri.
  • Deklaratif ve iç içe çalışma birimi.
  • Kerestecilik.
  • Ön / Sonrası koşullar (Sözleşmeye Göre Tasarım).

1
Bunlardan herhangi birinin basit yapıcı enjeksiyonu ile nasıl uygulanamayacağını anlamıyorum.
Billy ONeal

İyi bir tasarımla, yapıcı enjeksiyonu veya başka bir yöntem sizin için yeterli olabilir; bu IoC kaplarının avantajları yalnızca belirli durumlarda olabilir. WPF projesinde INotifyPropertyChanged ile verilen örnek böyle bir örnektir.
dodgy_coder
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.