Dependency Injection için en iyi tanım nedir?


10

Birisi bana her ulaştığında ve Bağımlılık Enjeksiyonunu kavramsal bir şekilde tanımlamamı ve yazılım tasarımında DI'yi kullanmanın gerçek artılarını ve eksilerini açıklamamı istediğinde. İD kavramlarını açıklamakta zorlandığımı itiraf ediyorum. Onlara her zaman tek sorumluluk ilkesi, miras kompozisyonu vb. Hakkında bilgi vermem gerekiyor.

Herkes geliştiriciler için DI tanımlamak için en iyi yolu açıklamak bana yardımcı olabilir?


2
Buradaki zorluk, DI'nin birbiriyle çelişen birçok tanımının olmasıdır. Ben "saf DI" duruş almak: Eğer tüm durum, veri vb sağlamak için parametrelerine dayanan bir fonksiyon varsa, o zaman bu fonksiyon DI kullanıyor. Diğer uçta, bazıları bir DI çerçevesi olmadan, bağımlılık enjeksiyonu olmadığını iddia edecektir (tabii ki yanlış olsalar da;)). Yani bir tanımı çivilemediğiniz sürece, ne olduğunu açıklamaya başlayamazsınız ...
David Arno

Yani, anladığım kadarıyla, bu sadece benim bir sorunum değil.
Tiago Sampaio



Her şey şudur: bağımlılık enjeksiyonu, bağımlılık tersini elde etmek için kullanılan bir tekniktir; diğer her şey bunun üzerine inşa edilmiş ekstra şeyler. Bu iki terimle "bağımlılık" kelimesinin biraz farklı anlamları olduğuna dikkat edin. Bağımlılık enjeksiyonunda, kodun bağımlı olduğu bileşeni ifade eder. Bağımlılığın tersine çevrilmesinde, (yönlendirilmiş) ilişkinin kendisini ifade eder - tersine çevirmek istediğimiz ilişki. İkincisi amaçtır, bu yüzden ana artılar ve eksiler aynıdır; artı nesne kullanım ömrü yönetimi gibi gerçek uygulama ile ilgili bazı ekstra endişeler.
Filip Milovanović

Yanıtlar:


22

Bağımlılık Enjeksiyonu , oldukça basit bir konsept için korkunç bir isim (IMO) 1'dir . İşte bir örnek:

  1. X yapan bir yönteminiz (veya yöntemli bir sınıfınız) var (ör. Veritabanından veri alma)
  2. X yapmanın bir parçası olarak, bahsedilen yöntem bir iç kaynak yaratır ve yönetir (örneğin a DbContext). Bu iç kaynak bağımlılık olarak adlandırılır
  3. Kaynağın (yani DbContext) oluşturulmasını ve yönetilmesini yöntemden kaldırırsınız ve bu kaynağı sağlamak için arayanın sorumluluğunu yaparsınız (bir yöntem parametresi olarak veya sınıfın somutlaştırılması üzerine)
  4. Şimdi bağımlılık enjeksiyonu yapıyorsunuz.


[1] : Daha düşük seviyeli bir geçmişe sahibim ve oturmak ve bağımlılık enjeksiyonunu öğrenmek aylarımı aldı çünkü isim DLL Enjeksiyonu gibi çok daha karmaşık bir şey olacağını ima ediyor . Visual Studio'nun (ve genel olarak geliştiricilerin ) bir projenin bağımlılıklar olarak bağımlı olduğu .NET kitaplıklarına (DLL'ler veya derlemeler ) başvurması hiç yardımcı olmuyor. Bağımlılık Walker (depends.exe) gibi bir şey bile var .


[Düzenle] Bazı demo kod bazıları için kullanışlı olacağını düşündüm, bu yüzden burada (C #).

Bağımlılık enjeksiyonu olmadan:

public class Repository : IDisposable
{
    protected DbContext Context { get; }

    public Repository()
    {
        Context = new DbContext("name=MyEntities");
    }

    public void Dispose()
    {
        Context.Dispose();
    }
}

Tüketiciniz daha sonra şöyle bir şey yapar:

using ( var repository = new Repository() )
{
    // work
}

Bağımlılık enjeksiyon modeli ile uygulanan aynı sınıf şöyle olacaktır:

public class RepositoryWithDI
{
    protected DbContext Context { get; }

    public RepositoryWithDI(DbContext context)
    {
        Context = context;
    }
}

Şimdi arayanın sınıfını a DbContextve geçmek (errm, enjekte etmek ) sorumluluğu :

using ( var context = new DbContext("name=MyEntities") )
{
    var repository = new RepositoryWithDI(context);

    // work
}

3
Bu Wikipedia'ya eklenmelidir.
Evorlor

2
Şimdi bir DbContext somutlaştırmak için arayanın sorumluluğu - Bence bu gerekli tüm bağımlılıkları somutlaştırmak için uygulamanın giriş noktasının sorumluluğu olacaktır. Bu nedenle, tüketicinin sadece kendi sözleşmesinde bağımlılık olarak gerekli türü tanıtması gerekir.
Fabio

@Fabio Olabilir. (Bu durumda, arayanın sorumluluğu, uygulama başlangıcında başlatılan yöntemi / sınıfa başlatılan kaynağı sağlamaktır.) Örneğimde, bu, bağımlılık enjeksiyonu kavramını açıklamak için bir gereklilik değil, çünkü .
Marc.2377

5

Soyut kavramlar gerçek dünya benzetmesi kullanılarak daha iyi açıklanır. Bu benim analojim:

Bir sandviç dükkanı işletiyorsun. Harika sandviçler yapıyorsunuz, ancak ekmeğin kendisi hakkında hiçbir şey bilmiyorsunuz. Sadece yumuşak beyaz ekmeğiniz var. Ekmeği sandviç haline getirmek için kullandığınız soslara tamamen odaklanıyorsunuz.

Ancak, bazı müşterileriniz gerçekten kahverengi ekmeği tercih eder. Bazıları kepekli olmayı tercih eder. Her iki şekilde de umursamıyorsunuz, benzer büyüklükte bir ekmek olduğu sürece herhangi bir şaşırtıcı sandviç yapabilirsiniz. Ayrıca, çeşitli ekmek türlerini tedarik etme ve stokları koruma konusunda ek sorumluluk almak da istemezsiniz. Birkaç çeşit ekmek stoklansanız bile, her zaman ekmeğin içinde makul bir şekilde öngöremediğiniz egzotik bir tadı olan bir müşteri olacaktır.

Böylece yeni bir kural oluşturuyorsunuz: müşteriler kendi ekmeğini getiriyor. Artık kendiniz ekmek vermiyorsunuz. Bu bir kazan-kazan durumu: müşteriler istedikleri tam ekmeğe sahip oluyorlar ve artık umursadığınız ekmeği tedarik etmekle uğraşmak zorunda değilsiniz. Sonuçta, bir sandviç üreticisi, fırıncı değilsiniz.

Oh, ve kendi ekmeğini satın almak istemeyen müşterileri karşılamak için, yandaki orijinal yumuşak beyaz ekmeklerinizi satan ikinci bir dükkan açıyorsunuz. Kendi ekmeğini getirmeyen müşteriler, varsayılan olanı almalı ve sonra onunla bir sandviç yapmak için size gelmelidir.

Mükemmel değil ama temel özelliği vurgular: tüketiciye kontrol vermek . İçsel kazan-kazan, artık kendi bağımlılıklarınızı edinmeniz gerekmemesi ve tüketicinizin bağımlılık seçiminde engellememesidir.


1
Bunu beğendim ama OP geliştiriciler için bir açıklama arıyor . İlk soyutlama iyidir, ancak er ya da geç, gerçek bir yaşam örneğine ihtiyaç duyar.
Robbie Dee

1
@RobbieDee: Desenin amacı net olduğunda, uygulaması da netleşir . Örneğin, Marc'ın cevabı kesinlikle doğrudur, ancak açıklamanın kullandığı örnek durumun karmaşık doğası nedeniyle şaşkına dönmüş gibi hissediyorum. Bu, "Bir gemi inşa etmek istiyorsanız, insanları odun toplamak için batırmayın ve onlara görev ve iş vermeyin, daha ziyade denizin sonsuz yoğunluğu için özlemini öğretin." . Ne yapacağımı açıklamak yerine, neden yapılacağını açıklamayı tercih ederim .
Flater

2
Tabii haklısın, ama yardım edemem ama somut bir örneğe ihtiyacım olacağını düşünüyorum - iştahımı uyandırmak için gerçek bir dosya sistemine veya veritabanına sahip olmamak gibi ama belki de sadece dar geliştirici görünümüm :)
Robbie Dee

1

Bunun basit cevabı:

Öncelikle bir sınıfın iyi tanımlanmış bir sorumluluğu olmalı ve bu kapsamın dışındaki her şey bu sınıfın dışında tutulmalıdır. Bununla birlikte, Bağımlılık Enjeksiyonu, bu endişelerin ayrılmasını sağlamak için bir "üçüncü taraf" yardımını kullanarak diğer sınıf B'den A sınıfına bir işlevsellik enjekte ettiğiniz ve A sınıfının kapsamı dışındaki bazı işlemleri tamamlamasına yardımcı olduğu zamandır.

Net Core verebileceğiniz oldukça iyi bir örnektir, çünkü bu çerçeve çok fazla bağımlılık enjeksiyonu kullanır. Genellikle, enjekte etmek istediğiniz hizmetler startup.csdosyada bulunur.

Elbette, öğrenci polimorfizm, arayüzler ve OOP Tasarım ilkeleri gibi bazı kavramların farkında olmalıdır.


0

Temelde basit bir kavramın etrafında çok fazla tüy ve bunkum var.

Ayrıca, oldukça basit bir şekilde kodla yapabildiğinizde " hangi çerçeveyi kullanmalıyım " ile başa çıkmak çok kolaydır .

Ben şahsen kullandığım tanım:

Y bağımlılığına sahip X davranışı göz önüne alındığında, bağımlılık enjeksiyonu, tesisiniz olmasa bile, Y örneği olma kriterlerini karşılayan herhangi bir Y'yi tedarik etme imkanını içerir.

Y'nin bir dosya sistemi veya veritabanı bağlantısı olduğu bazı örnekler olabilir.

Adedi gibi çerçeveler , iki katın (Y'nin sahte sürümleri) bir arabirim kullanılarak tanımlanmasına izin verir, böylece Y'nin bir veritabanı bağlantısı olduğu Y örneğine enjekte etmek mümkündür.

Bunun tamamen bir birim test endişesi olduğuna inanmak tuzağına düşmek kolaydır, ancak değişimin beklendiği ve tartışmasız olarak iyi bir uygulama olduğu herhangi bir kod parçası için çok yararlı bir modeldir.


0

Bir işlevin davranışını çalışma sırasında bu davranışı bir parametre aracılığıyla işleve ekleme yöntemiyle sağlıyoruz.

Strateji Paterni bağımlılık enjeksiyonunun mükemmel bir örneğidir.


0

Bunu doğru yapmak için önce bağımlılıkları ve enjeksiyonu tanımlamalıyız.

  • Bağımlılık: bir işlemin ihtiyaç duyduğu tüm kaynaklar.
  • Enjeksiyon: bu kaynağı işleme, tipik olarak bir yönteme argüman olarak geçirme.

İlkel örnek, iki değer katan bir yöntem olabilir. Açıkçası, bu yöntemlerin eklenmesi gereken değerlere ihtiyacı vardır. Eğer bunları argüman olarak ileterek sağlanırlarsa, bu zaten bir bağımlılık enjeksiyonu vakası olacaktır. Alternatif, işlenenleri özellikler veya global değişkenler olarak uygulamak olacaktır. Bu şekilde hiçbir bağımlılık enjekte edilmeyecek, bağımlılıklar dışarıdan alınabilecektir.

Bunun yerine özellikleri kullandığınızı ve bunları A ve B olarak adlandırdığınızı varsayalım. Adları Op1 ve Op2 olarak değiştirirseniz, Add yöntemini kırarsınız. Veya IDE'niz sizin için tüm isimleri güncelleyecekti, mesele, yöntemin de güncellenmesi gerekecek, çünkü dış kaynaklara bağımlılıkları var.

Bu örnek temeldir, ancak yöntemin görüntü gibi bir nesne üzerinde işlem gerçekleştirdiği veya bir dosya akışından okuduğu daha karmaşık örnekler hayal edebilirsiniz. Resmin nerede olduğunu bilmesini gerektiren yönteme ulaşmasını ister misiniz? Hayır. Yöntemin dosyanın kendisini açmasını, dosyayı nerede arayacağını ve hatta bir dosyadan okunacağını bilmesini ister misiniz? Hayır.

Amaç: Bir yöntemin işlevselliğini temel davranışına indirgemek ve yöntemi ortamından ayırmak. Birincisini ikincisini alarak alırsınız, bunu bağımlılık enjeksiyonunun tanımı olarak düşünebilirsiniz.

Avantajlar: yöntemin ortamına bağımlılıklar ortadan kaldırıldığı için, yöntemdeki değişiklikler çevreyi etkilemez ve bunun tersi de geçerlidir. => Uygulamanın bakımı (değiştirmesi) kolaylaşır.

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.