Bağımlılık Enjeksiyonu UnitTesting dışında buna değer mi?


17

Asla, başlattığı çeşitli nesnelerin farklı uygulamalarını kullanmak zorunda kalmayacak bir yapıcı göz önüne alındığında, DI'yi kullanmak hala pratik mi? Sonuçta, yine de birim testi yapmak isteyebiliriz.

Söz konusu sınıf yapıcısında birkaç sınıf daha başlatır ve kullandığı sınıflar oldukça belirgindir. Asla başka bir uygulama kullanmayacaktır. Bir arayüze program yapmaya çalışmaktan kaçınmamız haklı mı?



3
ÖPÜCÜK - her zaman en iyi yaklaşımdır.
Reactgular

5
Bence bu soru önerilen kopyadan daha spesifik. gelecekteki tasarım-değişiklikleri-veya-el-sorunu-çözmek-bu nedenle, ben bunu kapatmak
k3b

1
Test edilebilirlik bir sebep için yeterli değil mi?
ConditionRacer

Kendini cevaplamak kadar bir kopya gibi görünmüyor. Eğer asla, hiç olmazsa, bunun için tasarım gelecekteki değişiklikler için tasarlamaz. Mimari astronotlar bile sadece asla kötü değerlendirmeden olmayacak değişiklikler için tasarım yaparlar.
Steve314

Yanıtlar:


13

Bu, "asla, asla" nin doğru olduğundan emin olduğunuza bağlıdır (uygulamanızın kullanılacağı süre boyunca).

Genel olarak:

  • Tasarımınızı yalnızca test edilebilirlik için değiştirmeyin . Birim testleri size hizmet etmek için var, tersi değil.
  • Kendinizi tekrarlamayın. Sadece bir mirasçıya sahip olacak bir arayüz oluşturmak işe yaramaz.
  • Bir sınıf test edilemiyorsa, gerçek kullanım durumları için de esnek / genişletilemez. Bazen bu iyidir - bu esnekliğe ihtiyacınız yoktur, ancak basitlik / güvenilirlik / sürdürülebilirlik / performans / daha önemli olan her şey.
  • Eğer bilmiyorsanız, arayüz kodlayın. Gereksinimler değişir.

12
"Tasarımınızı yalnızca test edilebilirlik için değiştirmeyin" için neredeyse -1 verdi . Test edilebilirlik kazanmak için IMHO bir tasarımın değiştirilmesinin en önemli nedenlerinden biridir! Ama diğer noktalarınız iyi.
Doc Brown

5
@docBrown - (ve diğerleri) Burada birçokdan ve belki de çoğunluktan farklıyım. Zamanın ~% 95'i, işleri test edilebilir kılmak, onları esnek veya genişletilebilir hale getirir. Eğer tasarımında buna sahip (ya da tasarım eklemek) gerekir çoğu zaman - test edilebilirlik dibine batsın. Diğer% 5'inde ya bu tür bir esnekliği başka bir şey lehine engelleyen garip gereksinimleri vardır ya da o kadar temel / değişmez ki, özel testler olmasa bile, kırıldığını oldukça çabuk öğreneceksiniz.
Telastyn

4
emin olabilirsiniz, ancak yukarıdaki ilk ifadeniz "tek endişeniz test edilebilirlik durumunda olduğu gibi kötü tasarlanmış bir kod bırakın" olarak çok kolay yorumlanabilir.
Doc Brown

1
Neden sadece bir mirasçıya sahip olacak bir arayüz oluşturmak işe yaramaz? Arayüz bir sözleşme olarak çalışabilir.
kaptan

2
@kaptan - çünkü somut nesne bir sözleşme kadar iyi çalışabilir. İki tane yapmak , kodu iki kez yazmanız (ve değiştiğinde kodu iki kez değiştirmeniz) anlamına gelir. Kabul edilirse, arayüzlerin büyük çoğunluğunun birden fazla (test dışı) uygulaması olacaktır veya bu olasılığa hazırlanmak zorundasınız. Ancak, ihtiyacınız olan tek şey basit bir mühürlü nesne olduğu nadir durumlarda, doğrudan kullanın.
Telastyn

12

Bir arayüze program yapmaya çalışmaktan kaçınmamız haklı mı?

Bir arabirime karşı kodlamanın avantajı oldukça açık olsa da, kendinize tam olarak ne yaparak kazanıldığını sormalısınız.

Sonraki soru şudur: söz konusu sınıfın uygulamaları seçmenin sorumluluğunun bir parçası mı, değil mi? Durum böyle olabilir veya olmayabilir ve buna göre hareket etmelisiniz.

Sonuçta, bazı aptal kısıtlamaların maviden çıkma potansiyeli her zaman vardır. Aynı kod parçasını aynı anda çalıştırmak isteyebilirsiniz ve uygulamanın enjekte edilmesi olasılığı senkronizasyonda yardımcı olabilir. Veya uygulamanızın profilini oluşturduktan sonra, düz örneklemeden farklı bir tahsis stratejisi istediğinizi keşfedebilirsiniz. Ya da kesişen endişeler ortaya çıkıyor ve elinizde AOP desteği yok. Kim bilir?

YAGNI, kod yazarken gereksiz herhangi bir şey eklememeniz gerektiğini öne sürüyor. Programcıların farkında olmadan kodlarına ekleme eğilimi gösteren şeylerden biri gereksiz varsayımlardır. "Bu yöntem işe yarayabilir" veya "bu asla değişmeyecek" gibi. Her ikisi de tasarımınıza karmaşa katar.


2
YAGNI'yi burada DI için bir argüman olarak gösterdiği için +1 , buna karşı değil.
Doc Brown

4
@DocBrown: YAGNI da haklı göstermek için, burada kullanılabilir düşünülürse değil DI kullanarak. Bence bu daha çok YAGNI'nın her şey için yararlı bir önlem olduğu iddiası.
Steven Evers

1
Bizi birkaç kez kafasına
vuran YAGNI'da

@SteveEvers: Bağımlılık tersine çevirme prensibini göz ardı etmek için YAGNI kullanmak, YAGNI veya DIP'nin anlaşılmamasını veya belki de programlama ve akıl yürütmenin daha temel ilkelerinden bazılarını engelliyor. Eğer varsa sadece DIP görmezden gerektiğini gerek YAGNI basitçe doğası gereği uygulanamaz olduğu bir durum - için.
back2dos

@ back2dos: DI'nin 'belki gereksinimler' ve “kim bilir?” nedeniyle yararlı olduğu varsayımı. tam olarak YAGNI'nın savaşmak için tasarlandığı düşünce trenidir, bunun yerine onu ek takım ve altyapı için gerekçe olarak kullanıyorsunuz.
Steven Evers

7

Çeşitli parametrelere bağlıdır, ancak yine de DI'yi kullanmak istemenizin birkaç nedeni vardır:

  • Testin kendisi için oldukça iyi bir neden olduğuna inanıyorum
  • nesnenizin gerektirdiği sınıflar başka yerlerde de kullanılabilir - bunları enjekte ederseniz, kaynakları havuzlamanızı sağlar (örneğin, söz konusu sınıflar iş parçacığı veya veritabanı bağlantılarıysa - sınıflarınızın her birinin yeni oluşturmasını istemezsiniz bağlantıları)
  • diğer nesnelerin başlatılması başarısız olursa, yığının yukarısındaki kod muhtemelen problemlerle başa çıkmak için sınıfınızdan daha iyi olacaktır, bu da muhtemelen hataları iletecektir.

Alt satır: muhtemelen DI olmadan yaşayabilirsiniz, ancak DI kullanmanın daha temiz kodla sonuçlanma ihtimali vardır.


3

Bir program veya özellik tasarlarken, düşünce sürecinin bir parçası onu nasıl test edeceğiniz olmalıdır . Bağımlılık Enjeksiyonu test araçlarından biridir ve karışımın bir parçası olarak düşünülmelidir.

Bağımlılık Enjeksiyonu ve sınıflar yerine arayüzler kullanmanın ek faydaları, bir uygulama genişletildiğinde de yararlıdır, ancak daha sonra arama ve değiştirme kullanılarak kaynak koduna daha sonra kolayca ve güvenli bir şekilde uyarlanabilir. - çok büyük projelerde bile.


2
 > Dependency Injection worth it **outside** of UnitTesting?
 > Are we justified in avoiding trying to program to an interface?

Bu soruya verilen birçok cevap, eğer birim test yapmak istemiyorsanız, YAGNI olarak "buna ihtiyacınız olabilir .." olarak tartışılabilir.

Birim testlerin yanında hangi nedenlerin bir arayüze programlanması gerektiğini soruyorsanız

Evet , eğer kontrolün tersine çevrilmesi gerekiyorsa, UnitTesting dışında buna değer Bağımlılık Enjeksiyonu . Örneğin, bir modül uygulamasının katmanında erişilemeyen başka bir modül gerekiyorsa.

Örnek: gui=> businesslayer=> driver=> modüllerine sahipseniz common.

Bu senaryoda businesslayerkullanabilir driverancak driverkullanamazsınız businesslayer.

Daha yüksek driverseviyeli bir işlevsellik gerekiyorsa businesslayer, commonkatmandaki bir arabirimi uygulayan bu işlevselliği uygulayabilirsiniz . driversadece commonkatmandaki arayüzü bilmelidir .


1

Evet, - öncelikle, kodunuzu birim test araçları etrafında tasarlamanın bir nedeni olarak birim testini unutun, kod tasarımınızı yapay bir kısıtlamaya uyacak şekilde bükmek asla iyi bir fikir değildir. Araçlarınız sizi bunu yapmaya zorlarsa, daha iyi araçlar edinin (örneğin, sahte nesneler oluşturmak için daha fazla seçeneğe izin veren Microsoft Fakes / Moles).

Örneğin, test araçları özel yöntemlerle çalışmadığı için sınıflarınızı yalnızca herkese açık yöntemlere böler misiniz? (Hakim bilgeliğin, özel yöntemleri test etmeniz gerekmediğini iddia etmek olduğunu biliyorum, ancak bunun mevcut araçlarla bunu yapma zorluğuna bir tepki olduğunu hissediyorum, ayrıcalıkları test etmenize gerek olmayan gerçek bir tepki değil).

Sonuçta ne tür bir TDDer olduğunuza iniyor - Fowler'in tanımladığı gibi "sahte", kullandıkları araçlara uygun olarak kodu değiştirmeniz gerekiyorken, "klasik" testçiler doğada daha fazla entegrasyon olan testler oluşturuyor (yani sınıfı her birim için değil, birim olarak test edin) bu nedenle özellikle somut sınıflarla alay edebilen araçları kullanıyorsanız arayüzlere daha az ihtiyaç duyulur.


3
Özel yöntemlerin test edilmemesi gerektiği yönündeki bilgeliğin bunları test etmenin zorluğu ile ilgisi olduğunu düşünmüyorum. Özel bir yöntemde bir hata varsa, ancak nesnenin davranışını etkilemediyse, hiçbir şeyi etkilemez. Özel bir yöntemde nesnenin davranışını etkileyen bir hata varsa, bir nesnenin genel yöntemlerinden en az birinde başarısız veya eksik bir test vardır.
Michael Shaw

Bu, davranışı veya durumu test edip etmediğinizle ilgilidir. Özel yöntemlerin bir şekilde test edilmesi gerekiyor, tabii ki, ancak klasik bir TDD kişisiyseniz, "bir bütün olarak" sınıfını test ederek bunları test edersiniz, çoğu insanın kullandığı test araçları her yöntemi test etmeye odaklanır bireysel olarak ... ve benim açımdan, tam bir test yapma şansını kaçırdıklarından etkili bir şekilde test etmiyorlar. Bu yüzden size katılıyorum, TDD'nin günümüzde bazı (en çok?) İnsanların nasıl test yaptığını vurguladığını vurgulamaya çalışırken.
gbjbaanb

1

Bağımlılık Enjeksiyon ayrıca nesne olduğunu daha açık hale getirir HAS bağımlılıkları.

Başka biri nesnenizi naif bir şekilde (kurucuya bakmadan) kullanmaya gittiğinde, hizmet, bağlantı vb. Kurmaları gerektiğini bulacaklardır. Bu açık değildi çünkü onları kurucuya aktarmak zorunda kalmadılar . Bağımlılıkları geçmek neyin gerekli olduğunu daha net hale getirir.

Ayrıca, sınıfınızın SRP'yi ihlal ediyor olabileceği gerçeğini de gizlersiniz. Eğer çok fazla bağımlılık yaşıyorsanız (3'ten fazla), sınıfınız çok fazla şey yapıyor olabilir ve yeniden düzenlenmesi gerekir. Ancak bunları yapıcıda oluşturuyorsanız, bu kod kokusu gizlenecektir.


0

Buradaki her iki kampa da katılıyorum ve konu bence hala tartışmaya açık. YAGNI, kodumu varsayımlara uyacak şekilde değiştirmekle uğraşmamamı istiyor. Birim testi burada bir sorun değil çünkü bağımlılığın asla değişmeyeceğine inanıyorum. Ama başlangıçta Birim testi olsaydım, bu noktaya asla ulaşamazdım. Sonunda DI yolumu inceltecek gibi.

Senaryom için özellikle başka bir alternatif sunayım

Fabrika modeli ile bağımlılıkları tek bir yerde yerelleştirebilirim. Test yaparken, içeriği bağlama göre değiştirebilirim ve bu yeterince iyi. Bu, birkaç sınıf yapısının soyutlanmasının faydaları nedeniyle YAGNI'ya aykırı değildir.

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.