Bağımlılık enjeksiyon modelini kullanmak ne zaman uygun değildir?


124

Öğrenme (ve sevme) otomatik testlerinden beri kendimi hemen hemen her projede bağımlılık enjeksiyon modelini kullanırken buldum. Otomatik testle çalışırken bu modeli kullanmak her zaman uygun mudur? Bağımlılık enjeksiyonunu kullanmaktan kaçınmanız gereken durumlar var mıydı?


1
İlgili (muhtemelen yinelenmeyen) - stackoverflow.com/questions/2407540/…
Steve314

3
Golden Hammer anti-pattern'e benziyor. en.wikipedia.org/wiki/Anti-pattern
Cuga

Yanıtlar:


123

Temel olarak, bağımlılık enjeksiyonu nesnelerin doğası hakkında bazı (genellikle ama her zaman geçerli olmayan) varsayımlarda bulunur. Bunlar yanlışsa, DI en iyi çözüm olmayabilir:

  • İlk olarak, en temelde, DI nesne uygulamalarının sıkı bağlanmasının DAİMA kötü olduğunu varsayar . Bağımlılık İnversiyon Prensibi'nin özü budur: "bir bağımlılık asla bir somutluğa yapılmamalıdır; yalnızca bir soyutlama üzerine".

    Bu, somut uygulamadaki bir değişikliğe dayanarak değişime bağlı olan bağımlı nesneyi kapatır; ConsoleWriter'a bağlı bir sınıfın, çıktının bir dosyaya gitmesi gerekip gerekmediğini özellikle değiştirmeniz gerekecektir, ancak sınıf yalnızca bir Yazma () yöntemini ortaya çıkaran bir IWriter'a bağımlıysa, şu anda bir FileWriter ile kullanılmakta olan ConsoleWriter ve bağımlı sınıf farkı bilmeyecektir (Liskhov Değiştirme Prensibi).

    Ancak, bir tasarım ASLA her türlü değişikliğe kapatılamaz; Eğer IWriter arayüzünün tasarımı değişiyorsa, Write () parametresini eklemek için, uygulama nesnesinin / metodunun ve kullanımlarının üstünde ekstra bir kod nesnesinin (IWriter arayüzü) şimdi değiştirilmesi gerekir. Gerçek arayüzdeki değişikliklerin, söz konusu arayüzün uygulanmasındaki değişikliklerden daha muhtemel olması durumunda, gevşek birleştirme (ve gevşek bir şekilde bağlanmış bağımlılıkları Dİ), çözdüğünden daha fazla soruna neden olabilir.

  • İkincisi ve sonuç olarak, DI bağımlı sınıfın bir bağımlılık yaratmak için ASLA iyi bir yer olmadığını varsayar . Bu Tek Sorumluluk İlkesine gidiyor; Bir bağımlılık yaratan ve onu kullanan kodunuz varsa, o zaman bağımlı sınıfın SRP'yi ihlal eden (kullanım veya uygulamadaki bir değişiklik) değişmesi gerekebilecek iki nedeni vardır.

    Bununla birlikte, yine, DI için dolaylı katmanlar eklemek, var olmayan bir soruna bir çözüm olabilir; eğer bir mantığı bir bağımlılıkta kapsüllendirmek mantıklıysa, ancak bu mantık bir bağımlılığın sadece bu şekilde uygulanması ise, o zaman bağımlılığın gevşek şekilde bağlanmış olan çözünürlüğünü kodlamak daha acı verici olacaktır (enjeksiyon, servis yeri, fabrika). Sadece newonu kullanmak ve unutmak için.

  • Son olarak, DI doğası gereği tüm bağımlılıklar ve bunların uygulamalarıyla ilgili bilgiyi merkezileştirir . Bu, enjeksiyon işlemini yapan düzeneğin sahip olması gereken referans sayısını arttırır ve çoğu durumda gerçek bağımlı sınıfların meclislerinin gerektirdiği referans sayısını azaltmaz.

    BAZI, NEREDE, “noktaları bağlamak” ve bu bağımlılığı sağlamak için bağımlılık, bağımlılık arayüzü ve bağımlılık uygulaması hakkında bilgi sahibi olmalıdır. DI, tüm bu bilgileri çok yüksek bir seviyede, bir IoC kabına ya da bağımlılıkları nemlendirmesi gereken (ya da fabrika metotlarını sağlaması gereken) ana form ya da Kontrolör gibi “ana” nesneler yaratan kodda koyma eğilimindedir. Bu, uygulamanızın yüksek seviyelerinde zorunlu olarak sıkı bir şekilde bağlanmış çok sayıda kod ve birçok montaj referansı koyabilir, bu bilgiyi yalnızca gerçek bağımlı sınıflardan gizlemek için bu bilgiyi gerektirir (ki bu çok basit bir bakış açısıyla bu bilgiye sahip olmak için en iyi yer;

    Ayrıca normal olarak söz konusu referansları kodun altından kaldırmaz; Bir bağımlı hala, üç yerden birindeki bağımlılığı için arayüzü içeren kütüphaneye başvurmalıdır:

    • hepsi uygulama merkezli hale gelen tek bir "Arayüzler" düzeneğinde,
    • her biri birincil uygulama (lar) ın yanında, bağımlılıklar değiştiğinde bağımlıları tekrar derlememenin avantajını ortadan kaldırarak, veya
    • montaj sayısını azaltan yüksek yapılı montajlardaki bir veya iki parça, "tam yapım" sürelerini önemli ölçüde arttırır ve uygulama performansını düşürür.

    Bütün bunlar, bir problemin çözülmeyeceği yerlerde tekrar çözmek için.


1
SRP = merak eden herkes için tek sorumluluk ilkesi.
Theodore Murdock

1
Evet, ve LSP Liskov Değişimi ilkesidir; A'ya bağımlılık verildiğinde, bağımlılık, A'dan türeyen B ile başka bir değişiklik yapılmadan karşılanabilmelidir.
KeithS

Bağımlılık enjeksiyonu özellikle A sınıfını B sınıfından D sınıfından vb. almanız gerektiğinde yardımcı olur (bu durumda DI çerçevesi) fakir insan enjeksiyonundan daha az montaj bloğu oluşturabilir. ayrıca DI'nin neden olduğu bir darboğazım hiç olmadı .. bakım maliyetini düşünün, hiçbir zaman cpu maliyetini
düşürmeyin

Başka bir varsayım, "bir bağımlılık her yerde değişirse değişirse" olur mu? Yoksa yine de tüm tüketici sınıflarına bakmak zorundasın
Richard Tingle

3
Bu cevap, enjeksiyon bağımlılıklarının test edilebilme kabiliyetine karşı sert kodlama etkisini ele almamaktadır. Ayrıca bkz. Açık Bağımlılıklar İlkesi ( deviq.com/explicit-dependencies-principle )
ssmith

30

Bağımlılık enjeksiyon çerçevelerinin dışında, bağımlılık enjeksiyonu (yapıcı enjeksiyon veya ayarlayıcı enjeksiyon yoluyla) neredeyse sıfır toplamlı bir oyundur: nesne A ile bağımlılık B arasındaki bağlantıyı azaltırsınız, ancak şimdi A örneğine ihtiyaç duyan herhangi bir nesne ayrıca nesne B'yi de oluşturur.

A ve B arasındaki kuplajı hafifçe azalttınız, ancak A'nın kapsüllemesini azalttınız ve A'nın bir bağımlılığını da birleştirerek A'nın bir örneğini oluşturması gereken A ve herhangi bir sınıf arasındaki kuplajı arttırdınız.

Dolayısıyla bağımlılık enjeksiyonu (çerçeve olmadan) faydalı olduğu kadar eşit derecede zararlıdır.

Ancak, ekstra maliyet genellikle kolayca haklı çıkarılabilir: müşteri kodu bağımlılığın nesnenin kendisinden daha fazla nasıl kurulacağı hakkında daha fazla şey biliyorsa, bağımlılık enjeksiyonu gerçekten eşleşmeyi azaltır; Örneğin, bir Tarayıcı girdiyi ayrıştırmak için bir girdi akışının nasıl elde edileceği veya oluşturulacağı ya da müşteri kodunun girdiden ayrıştırmak istediği şey hakkında pek bir şey bilmediğinden, bir giriş akışının yapıcı enjeksiyonu açık bir çözümdür.

Test, sahte bağımlılıkları kullanabilmek için başka bir gerekçedir. Bu, yalnızca bağımlılıkların enjekte edilmesini sağlayan testler için kullanılan fazladan bir yapıcı eklemek anlamına gelir: yapıcılarınızı her zaman enjekte edilecek bağımlılıklara gerek duyacak şekilde değiştirirseniz, aniden, bağımlılıklarınızı 'bağımlılıkları' bağımlılıklar hakkında bilmek zorundasınız. doğrudan bağımlılıklar ve hiçbir iş yapamazsınız.

Yardımcı olabilir, ancak kesinlikle her bağımlılık için kendinize sormalısınız, testin maliyeti faydalı mı ve test sırasında gerçekten bu bağımlılıkla alay etmek isteyeceğim mi?

Bir bağımlılık enjeksiyon çerçevesi eklendiğinde ve bağımlılıkların yapımı müşteri koduna değil, çerçeveye bırakıldığında, maliyet / fayda analizi büyük ölçüde değişir.

Bağımlılık enjeksiyon çerçevesindeki değişimler biraz farklıdır; Bir bağımlılığı enjekte ederek kaybettiğiniz şey, hangi uygulamaya dayandığınızı kolayca bilme ve hangi otomatik bağımlılık işlemlerine güveneceğinize karar verme sorumluluğunu değiştirmektir (örneğin bir @ Enjekte edilmiş Foo'ya ihtiyacımız varsa). @ Foo'yu ve enjekte edilen bağımlılıkları mevcut olan) veya her bir kaynak için hangi sağlayıcıların kullanılması gerektiğini belirten bazı üst düzey yapılandırma dosyalarına veya örneğin ikisinin bir hibritine sahip olması gereken (örneğin, Bir yapılandırma dosyası kullanarak, gerekirse geçersiz kılınabilecek bağımlılıklar için otomatik bir çözünürlük işlemi olabilir).

Yapıcı enjeksiyonunda olduğu gibi, bunu yapmanın avantajının, yine de, yapma maliyetine çok benzeyen bir sonuç olduğunu düşünüyorum: güvendiğiniz verileri kimin sağladığını ve çoklu potansiyel olup olmadığını bilmek zorunda değilsiniz. sağlayıcılar, sağlayıcıları kontrol etmek için tercih edilen sırayı bilmek zorunda değilsiniz, veriye ihtiyaç duyan her konumun tüm potansiyel sağlayıcıları vb. kontrol ettiğinden emin olun, çünkü bunların tümü bağımlılık enjeksiyonuyla yüksek seviyede ele alınır. platformudur.

Kişisel olarak DI çerçeveleriyle ilgili çok fazla deneyimim olmasa da, benim izlenimim, ihtiyaç duyduğunuz veri veya hizmetin doğru sağlayıcısını bulma baş ağrısının baş ağrısından daha yüksek bir maliyete sahip olması durumunda, maliyetten daha fazla fayda sağlamalarıdır. bir şey başarısız olduğunda, derhal yerel olarak bilmediğinizden, hangi kodun kodunuzda daha sonra başarısızlığa neden olan kötü verileri sağladığını bilmek.

Bazı durumlarda, DI çerçevelerinin ortaya çıkması durumunda bağımlılıkları gizleyen diğer örüntüler (örn. Hizmet yer belirleyicileri) zaten kabul edilmiş (ve belki de onların değerini kanıtlamış) ve DI çerçeveleri de benimsemek gibi bazı rekabet avantajı sundukları için kabul edilmiştir. daha az boyunduruk kod kodu veya potansiyel olarak hangi sağlayıcının kullanımda olduğunu belirlemek gerektiğinde bağımlılık sağlayıcıyı gizlemek için potansiyel olarak daha az şey yapmak.


6
Testlerde bağımlılıkla alay etmeye dair kısa bir yorum ve "bağımlılıklarınız" bağımlılıklarınız "bağımlılıklarınız hakkında bilmek zorundasınız ... ... Bu doğru değil. Sahte bir enjekte ediliyorsa, bazı somut uygulamaların bağımlılıklarını bilmek veya bakım yapmak gerekmez. Birinin , test edilen sınıfın sahte (ler) tarafından karşılanan doğrudan bağımlılıkları hakkında bilmesi gerekir .
Eric King,

6
Yanlış anlıyorsun, alay enjekte ettiğin zamandan bahsetmiyorum, gerçek koddan bahsediyorum. Sırasıyla D bağımlılığı olan C bağımlılığına sahip B sınıfına sahip A sınıfını ele alın. D'nin A olması durumunda B, B'nin C, C yapısının D'yi yapması gerekir. Enjeksiyon ile A yapısının önce B yapmasını, B'yi inşa etmek için önce C'yi ve C'yi inşa etmek için önce D'yi inşa etmelisiniz. Bu nedenle A sınıfı, B'yi inşa etmek için artık bir bağımlılığın bağımlılığı olan D hakkında bilgi sahibi olmak zorundadır. Bu, aşırı bağlanmaya neden olur.
Theodore Murdock

1
Sadece bağımlılıkların enjekte edilmesini sağlayan testler için kullanılan fazladan bir kurucuya sahip olmanın maliyeti çok fazla olmaz. Söylediklerimi revize etmeye çalışacağım.
Theodore Murdock,

3
Bağımlılık enjeksiyonu dosenti sadece sıfır toplamlı bir oyunda bağımlılıkları hareket ettirir. Bağımlılarınızı zaten var olan yerlere taşıyorsunuz: ana proje. Bağımlılıkların ancak çalışma zamanında çözülebildiğinden emin olmak için, örneğin hangi sınıfların isim alanları veya neye göre somut olduğunu belirleyerek konvansiyonel yaklaşımları bile kullanabilirsiniz. Bunun saf bir cevap olduğunu söylemeliyim
Sprague

2
@Sprague Bağımlılık enjeksiyonu, uygulanmaması gereken durumlarda uygularsanız, biraz negatif toplamlı bir oyunda bağımlılıklar etrafında hareket eder. Bu cevabın amacı insanlara bağımlılık enjeksiyonunun doğal olarak iyi olmadığını, doğru koşullarda inanılmaz derecede yararlı olan bir tasarım deseni olduğunu, ancak normal koşullarda (en azından çalıştığım programlama alanlarında, haksız bir maliyet olduğunu) hatırlatmaktır. , Bazı alanlarda diğerlerine göre daha sık yararlı olduğunu biliyorum). DI bazen bir terim ve kendi içinde bir son haline gelir, bu da noktayı özlüyor.
Theodore Murdock

11
  1. veritabanı varlıkları oluşturuyorsanız, denetleyicinize değil, enjekte edeceğiniz bazı fabrika sınıflarına sahip olmalısınız.

  2. Ints veya Longs gibi ilkel nesneler oluşturmanız gerekiyorsa Ayrıca tarih, kılavuz vb. Gibi standart kütüphane nesnelerinin çoğunu "el ile" oluşturmalısınız.

  3. Konfigürasyon dizgilerini enjekte etmek istiyorsanız, bazı konfigürasyon nesnelerini enjekte etmek daha iyi bir fikir olabilir (genel olarak basit tipleri anlamlı objelere sarmanız önerilir: int sıcaklıkInCelsiusDegrees -> CelciusDeegree sıcaklık)

Servis bulucuyu bağımlılık enjeksiyonu alternatifi olarak kullanmayın, anti-pattern, daha fazla bilgi: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx


Bütün noktalar, tamamen kullanmamak yerine farklı enjeksiyon formlarını kullanmakla ilgilidir. Olsa bağlantı için +1.
Jan Hudec

3
Servis Bulucu bir anti-kalıp değildir ve linklendiğiniz blogdaki adam kalıplarda uzman değildir. StackExchange ile ünlü olması, yazılım tasarımında bir tür kötüye kullanımdır. Martin Fowler (Kurumsal Uygulama Mimarisinin temel kalıplarının yazarı) konuyla ilgili daha makul bir görüşe sahip: martinfowler.com/articles/injection.html
Colin

1
@Colin, aksine, Servis Bulucu kesinlikle bir anti-paterndir ve kısaca burada nedeninin nedenidir .
Kyralessa

@Kyralessa - DI çerçevelerinin dahili olarak servisleri bulmak için Servis Belirleme modelini kullandığını biliyorsunuz, değil mi? Her ikisinin de uygun olduğu durumlar vardır ve StackExchange’in bazılarının atmak istediğinden nefret etmesine rağmen, ikisi de anti-patern değildir.
Colin

Tabii ve arabam dahili olarak pistonlar ve bujileri ve sadece araba kullanmak isteyen sıradan bir insan için iyi bir arayüz olmayan pek çok şeyi kullanıyor.
Kyralessa

8

Projenizi sürdürülebilir ve test edilebilir hale getirerek bir şey kazanmaya dayanmadığınızda.

Cidden, genel olarak IoC ve DI'yi seviyorum ve zamanın% 98'inin bu modeli başarısız olmadan kullanacağımı söyleyebilirim. Mantığı uygulamadan ayırdığı için, kodunuzu farklı ekip üyeleri ve farklı projeler tarafından tekrar tekrar kullanabileceğiniz çok kullanıcılı bir ortamda özellikle önemlidir. Günlüğe kaydetme bunun bir örneğidir, bir sınıfa enjekte edilen bir ILog arabirimi, günlüğe kaydetme çerçevesini-du-jour'unuza takmaktan sadece bin kat daha bakımlıdır, çünkü başka bir projenin aynı günlüğe kaydetme çerçevesini kullanacağına dair hiçbir garantiniz yoktur. hiç biri!).

Ancak, uygulanabilir bir model olmadığı zamanlar vardır. Örneğin, geçersiz kılınamayan bir başlatıcı (WebMethods, sana bakıyorum, ancak Program sınıfınızdaki Main () yönteminiz başka bir örnektir) olan statik bağlamda uygulanan işlevsel giriş noktaları, başlangıçta enjekte edilen bağımlılıklara sahip olamaz. saati. Ayrıca bir prototipin veya herhangi bir araştırıcı kodun da kötü bir aday olduğunu söyleyeceğim kadarıyla giderdim; DI'nin faydaları orta ila uzun vadeli faydalardır (test edilebilirlik ve bakım kolaylığı), bir kod parçasının çoğunluğunu bir hafta içinde atacağınızdan eminseniz ya da bu nedenle izole ederek hiçbir şey elde edemeyeceğinizi düşünüyorsanız Bağımlılıklar, normalde kodu çalıştırmak için bağımlılıkları sınamak ve yalıtmak için harcadığınız zamanı harcarsınız.

Sonuçta, hiçbir zamanın% 100'ü uygulanabilir olmadığı için herhangi bir metodolojiye veya desene pragmatik bir yaklaşım benimsemek daha mantıklıdır.

Unutulmaması gereken bir şey otomatik test Yorumunuz şudur: Bu benim tanımı otomatik olduğu fonksiyonel bir web bağlamında ise örnek metne selenyum testleri için testleri. Bunlar genellikle tamamen kara kutu testleridir ve kodun iç işleyişini bilmeye gerek yoktur. Birim veya Entegrasyon testlerine atıfta bulunuyorsanız, DI modelinin hemen hemen her zaman bu tür beyaz kutu testlerine dayanan herhangi bir projeye uygulanabileceğini söyleyebilirim, örneğin, örneğin DB'nin bulunmasına gerek kalmadan DB'ye dokunan yöntemler.


Giriş yapmanın ne demek istediğini anlamadım. Kuşkusuz, tüm kayıt cihazları aynı arayüze uymayacak, bu nedenle bu projeler günlüğe kaydetme yöntemi ile belirli bir kayıt cihazı (kayıt cihazlarını kolayca değiştirebilmeyi istediğinizi varsayarak) arasında çevirmek için kendi sargınızı yazmanız gerekecektir. Peki ondan sonra DI sana ne veriyor?
Richard Tingle

@RichardTingle Günlük sarmalayıcınızı bir arabirim olarak tanımlamanız gerektiğini ve ardından birden fazla soyutlamayı saran tek bir günlükleme sınıfı kullanmak yerine, her bir harici günlükleme hizmeti için bu arabirimin hafif bir uygulamasını yazdığınızı söyleyebilirim. Önerdiğiniz aynı kavram ama farklı bir seviyede soyutlanmışsınız.
Ed James,

1

Diğer cevaplar teknik yönlere odaklanırken pratik bir boyut eklemek istiyorum.

Yıllar geçtikçe, Bağımlılık Enjeksiyonunu uygulamaya koymanın yerine getirilmesi durumunda karşılanması gereken birkaç pratik şartın olduğu sonucuna vardım.

  1. Bunu tanıtmak için bir sebep olmalı.

    Bu çok açık gibi görünebilir, ancak kodunuz yalnızca veritabanından bir şey alırsa ve herhangi bir mantık olmadan döndürürse, bir DI kapsayıcı eklemek, gerçek olmayan yararlarla işleri daha karmaşık hale getirir. Entegrasyon testi burada daha önemli olurdu.

  2. Takımın eğitimli ve gemide olması gerekiyor.

    Takımın çoğunluğu gemide olmadıkça ve DI'nin kontrol kabının ters çevrilmesini eklemeyi anlamadığı sürece, işleri yapmak için bir başka yol haline gelir ve kod tabanını daha da karmaşık hale getirir.

    Eğer DI takımın yeni bir üyesi tarafından tanıtılırsa, onu anlarlar ve beğenirler ve sadece iyi olduklarını göstermek isterler. VE ekip aktif olarak yer almazsa, aslının kalitesini düşürme riski vardır. kod.

  3. Test etmen gerek

    Dekuplaj genellikle iyi bir şey olsa da, DI bir bağımlılığın çözümünü derleme zamanından çalışma zamanına taşıyabilir. İyi test etmiyorsanız, bu aslında oldukça tehlikelidir. Çalışma süresi çözümleme hataları izlemek ve çözmek için maliyetli olabilir.
    (Testinizden yaptığınız açıktır, ancak çoğu takım DI'nin gerektirdiği ölçüde test yapmaz.)


1

Bu tam bir cevap değil, sadece başka bir nokta.

Bir kez başlayan bir uygulamanız olduğunda, uzun süre çalışır (bir web uygulaması gibi) DI iyi olabilir.

Birçok kez başlayan ve daha kısa süreler için çalışan (bir mobil uygulama gibi) bir uygulamanız olduğunda, muhtemelen kabı istemezsiniz.



@ MichaelFreidgeim Bağlamı başlatmak zaman alır, genellikle Spring gibi DI kapları oldukça ağırdır. Sadece bir sınıfa merhaba bir dünya uygulaması yapın ve Spring ile bir tane yapın ve her ikisine de 10 kez başlayın ve ne demek istediğimi anlayacaksınız.
Koray Tugay

Bireysel DI konteyner ile ilgili bir sorun gibi geliyor. Net dünyasında DI konteynerleri için temel bir sorun olarak başlatma zamanını duymadım
Michael Freidgeim

1

Temel OOP ilkelerinin kullanmayı deneyin: kullanım kalıtım , ortak işlevselliği ayıklamak için saklanması (sakla) şeyler, o korumalı / dahili / özel üyeler / türlerini kullanarak dış dünyadan korunmalıdır. Yalnızca testler için kod enjekte etmek için güçlü bir test çerçevesi kullanın, örneğin https://www.typemock.com/ veya https://www.telerik.com/products/mocking.aspx .

Sonra DI ile tekrar yazmaya çalışın ve genellikle DI ile göreceğiniz kodu karşılaştırın:

  1. Daha fazla arayüzünüz var (daha fazla tür)
  2. Genel yöntemlerin imzalarının kopyalarını oluşturdunuz ve bunu iki katına çıkarmak zorunda kalacaksınız (bir parametreyi basitçe bir kez değiştiremezsiniz, iki kez yapmak zorunda kalacaksınız, temel olarak tüm yeniden düzenleme ve gezinme olasılıkları daha karmaşık hale geliyor)
  3. Bazı derleme hatalarını çalışma zamanı hatalarını taşımak için taşıdınız (DI ile kodlama sırasında bazı bağımlılığı görmezden gelebilirsiniz ve test sırasında ortaya çıkacağından emin değilsiniz)
  4. Kapsüllemeni açtın. Artık korunan üyeler, iç tipler vb
  5. Genel kod miktarı arttırıldı

Gördüğüm kadarıyla neredeyse her zaman DI ile kod kalitesinin düştüğünü söyleyebilirim.

Ancak, sınıf beyanında yalnızca "genel" erişim değiştiricisini ve / veya üyeler için genel / özel değiştiricileri kullanıyorsanız ve / veya pahalı test araçları satın alma seçeneğiniz yoksa ve aynı zamanda yapabileceğiniz birim testine ihtiyacınız varsa, Entegre testlerle değiştirilmez ve / veya enjekte etmeyi düşündüğünüz sınıflar için arayüzlere zaten sahipsiniz, DI iyi bir seçimdir!

ps muhtemelen bu yazı için çok fazla eksi alacağım, inanıyorum çünkü modern geliştiricilerin çoğu anahtar kelimeyi nasıl ve niçin kullanacaklarını ve bileşenlerin eşleşmesini nasıl azaltabileceklerini ve nihayet neden azaltacaklarını anlamıyorlar. kodlamaya ve karşılaştırmaya çalış


0

Bağımlılık Enjeksiyonuna bir alternatif Servis Bulucu kullanmaktır . Bir Servis Belirleyici'nin anlaşılması, hata ayıklaması daha kolaydır ve özellikle DI çerçevesi kullanmıyorsanız bir nesnenin oluşturulmasını kolaylaştırır. Hizmet Konumlandırıcılar, dış statik bağımlılıkları yönetmek için iyi bir kalıptır , örneğin veri erişim katmanınızdaki her nesneye geçirmeniz gereken bir veritabanı.

Ne zaman eski kodu üstlenmeden , Dependency Injection için daha Servis Locator refactor genellikle daha kolaydır. Tek yapmanız gereken servis örnekleriyle servis örneklerini değiştirmek ve ardından birim testinizde hizmeti sahte yapmak.

Ancak, Servis Belirleyicinin bazı olumsuz yanları vardır . Bir sınıfın bağımlılıklarını bilmek daha zordur, çünkü bağımlılıklar sınıfın uygulamasında, kurucularda veya ayarlayıcılarda gizli değildir. Aynı hizmetin farklı uygulamalarına dayanan iki nesne oluşturmak zor veya imkansızdır.

TLDR : Sınıfınızın statik bağımlılıkları varsa veya eski kodu yeniden değerlendiriyorsanız, bir Hizmet Bulucu muhtemelen DI'den daha iyidir.


12
Servis Bulucu, kodunuzdaki bağımlılıkları gizler . Kullanmak için iyi bir model değil.
Kyralessa

Statik bağımlılıklar söz konusu olduğunda, arayüzleri uygulayan cephelerin üzerine tokatlanmış cepheleri görmeyi tercih ederim. Bunlar daha sonra enjekte edilen bağımlılık olabilir ve sizin için statik el bombasına düşerler.
Erik Dietrich,

@Kyralessa Kabul ediyorum, bir Servis Belirleyici'nin birçok dezavantajı vardır ve DI neredeyse her zaman tercih edilir. Ancak, kuralın tüm programlama ilkelerinde olduğu gibi, birkaç istisna olduğuna inanıyoruz.
Garrett Hall

Hizmet konumunun ana kabul edilen kullanımı, bir "strateji seçicisi" sınıfının kullanılacak stratejiyi bulmak için yeterince mantık verildiği ve onu geri ya da aramayı ilettiği bir Strateji kalıbı içerisindedir. Bu durumda bile, strateji toplayıcı aynı mantık verilen bir IoC konteyneri tarafından sağlanan bir fabrika metodu için bir cephe olabilir; Bunu çözmenizin nedeni, en gizli olduğu yere değil, ait olduğu yere mantık koymaktır.
KeithS

Martin Fowler'tan alıntı yapmak gerekirse, "(DI ve Servis Bulucu) arasındaki seçim, yapılandırmayı kullanımdan ayırma ilkesinden daha az önemlidir". DI'nin HER ZAMAN daha iyi olduğu fikri hogwash. Eğer hizmet global olarak kullanılıyorsa, DI kullanımı daha zahmetli ve kırılgandır. Ek olarak, DI uygulamaların çalışma zamanına kadar bilinmediği eklenti mimarileri için daha az uygundur. Debug.WriteLine () ve benzerlerine her zaman ek argümanlar iletmenin ne kadar garip olacağını düşünün!
Colin,
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.