Zavallı Adamın Bağımlılık Enjeksiyonu, eski bir uygulamaya test edilebilirliği tanıtmak için iyi bir yol mu?


14

Geçen yıl, Bağımlılık Enjeksiyonu ve bir IOC kapsayıcısı kullanarak yeni bir sistem oluşturdum. Bu bana DI hakkında çok şey öğretti!

Ancak, kavramları ve uygun kalıpları öğrendikten sonra bile, kodu çözmek ve bir IOC kapsayıcısını eski bir uygulamaya tanıtmak için bir zorluk olduğunu düşünüyorum. Uygulama, gerçek bir uygulamanın ezici olacağı noktaya kadar büyüktür. Değer anlaşılsa ve zaman tanınsa bile. Kim böyle bir şey için zaman verdi ??

Amaç, iş mantığına birim testleri getirmektir!
Test önleyici veritabanı çağrıları ile iç içe iş mantığı.

Makaleleri okudum ve bu Los Techies makalesinde açıklanan Zavallı Adamın Bağımlılık Enjeksiyonunun tehlikelerini anlıyorum . Hiçbir şeyi gerçekten ayırmadığını anlıyorum .
Uygulamalar yeni bağımlılıklar gerektirdiğinden, sistem genelinde yeniden düzenlemeyi içerebileceğini anlıyorum. Herhangi bir boyutta yeni bir projede kullanmayı düşünmem.

Soru: o kadar Poor Man DI kullanmak iyi mi tanıtmak bir eski uygulamalara test edilebilir ve yuvarladınmı?

Buna ek olarak, Zavallı Adam'ın DI'sini gerçek Bağımlılık Enjeksiyonuna temel bir yaklaşım olarak kullanmak, ilkenin ihtiyacı ve faydaları konusunda eğitim vermenin değerli bir yolu mudur?

Bir veritabanı çağrı bağımlılığı ve soyut bir arabirimin arkasına çağrı olan bir yöntemi refactor olabilir? Basit bir şekilde bu soyutlamaya sahip olmak, bu yöntemi test edilebilir hale getirecektir, çünkü sahte bir uygulama bir yapıcı aşırı yüklenmesi yoluyla aktarılabilir.

Yol boyunca, çaba destekçileri kazandığında, proje bir IOC konteyneri uygulamak için güncellenebilir ve soyutlayıcıları alan inşaatçılar orada olacaktı.



2
Sadece bir not. I consider it a challenge to decouple code and introduce an IOC container into a legacy applicationtabii ki öyle. Adı teknik borç. Bu nedenle, herhangi bir büyük yenilemeden önce, tercih edilen küçük ve sürekli refraktörler. Büyük tasarım kusurlarını azaltmak ve IoC'ye geçmek daha az zor olacaktır.
LAIV

Yanıtlar:


25

NerdDinner'de Zavallı Adamın Enjeksiyonu hakkındaki eleştirinin, bir DI Kabı kullanıp kullanmadığınızı , sınıflarınızı doğru bir şekilde ayarlamaktan daha az ilgisi vardır .

Makalede,

public class SearchController : Controller {

    IDinnerRepository dinnerRepository;

    public SearchController() : this(new DinnerRepository()) { }

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

çünkü yanlıştır, çünkü ilk kurucu sınıfı oluşturmak için uygun bir geri dönüş mekanizması sağlarken, aynı zamanda sıkı sıkıya bağlı bir bağımlılık yaratır DinnerRepository.

Elbette doğru çözüm, Los Techies'in önerdiği gibi, bir DI kabı eklemek değil , rahatsız edici kurucuyu kaldırmaktır.

public class SearchController : Controller 
{
    IDinnerRepository dinnerRepository;

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

Kalan sınıf şimdi bağımlılıklarını uygun şekilde tersine çevirdi. Artık bu bağımlılıkları istediğiniz gibi enjekte edebilirsiniz.


Düşünceleriniz için teşekkürler! "Rahatsız edici yapıcı" yı ve bundan nasıl kaçınmamız gerektiğini anlıyorum. Bu bağımlılığa sahip olmanın hiçbir şeyi çözmediğini anlıyorum, ancak birim testlere izin veriyor. DI'yi tanıtmanın ve birim testlerini olabildiğince çabuk yerine koymanın erken tarafındayım. Oyunun başlangıcında bir DI / IOC Konteyner veya fabrikasının komplikasyonlarından kaçınmaya çalışıyorum. Daha önce de belirtildiği gibi, DI için destek büyüdüğünde, bir Konteyner uygulayabilir ve bu "rahatsız edici kurucuları" kaldırabiliriz.
Airn5475

Ünite testleri için varsayılan kurucu gerekli değildir. Sahte nesne de dahil olmak üzere sınıfa onsuz istediğiniz bağımlılığı verebilirsiniz.
Robert Harvey

2
@ Airn5475 çok fazla soyutlamamaya dikkat edin . O testler anlamlı davranışları test etmelidir - Bir o test XServicebir bir parametre geçirir XRepositoryne dönene aşırı kimseye yararlı değildir ve dönüş ve gelmez genişletilebilirlik ya yolunda size çok ver. Anlamlı davranışı test etmek ve bileşenlerinizin o kadar dar olmadığından emin olmak için birim testlerinizi yazın ve tüm mantığınızı kompozisyon kökünüze kaydırın.
Ant P

Rahatsız edici kurucu dahil olmak üzere birim testleri için nasıl yardımcı olacağını anlamıyorum, kesinlikle tersi? Sorun yaratan yapıcıyı çıkarın, böylece DI düzgün bir şekilde uygulanır ve nesneleri somutlaştırırken alaylı bir bağımlılığa geçer.
Rob

@Rob: Öyle değil. Varsayılan kurucunun geçerli bir nesneyi ayağa kaldırması için uygun bir yoldur.
Robert Harvey

15

Burada, "fakir adamın DI'sı" ne ait olduğu konusunda yanlış bir varsayım yaparsınız.

Halen kuplaj oluşturan bir "kısayol" yapıcısı olan bir sınıf oluşturmak , zavallı adamın DI'sı değildir.

Bir kap kullanmamak ve tüm enjeksiyonları ve eşlemeleri manuel olarak oluşturmak , zavallı adamın DI'sıdır.

"Zavallı adamın DI" terimi kötü bir şey gibi geliyor. Bu nedenle, "saf DI" terimi bu günlerde daha olumlu geldiği ve süreci daha doğru bir şekilde tanımladığı için teşvik edilmektedir.

Sadece mevcut bir uygulamaya DI'yi tanıtmak için zavallı adamın / saf DI'yi kullanmak kesinlikle iyi değil, aynı zamanda birçok yeni uygulama için DI'yi kullanmanın geçerli bir yoludur. Ve dediğin gibi, herkes bir IoC konteynerinin “büyüsüne” ilişkin sorumluluğu ele almadan önce, DI'nin nasıl çalıştığını gerçekten anlamak için en az bir projede saf DI kullanmalıdır.


8
"Zavallı adam" veya "Saf" DI, hangisini tercih ederseniz edin, IoC kaplarıyla ilgili birçok sorunu da azaltır. Her şey için IoC kapları kullanıyordum, ancak zaman geçtikçe onlardan tamamen kaçınmayı tercih ediyorum.
Ant P

7
@AntP, ben seninleyim: Bugünlerde% 100 saf DI ve aktif olarak konteynerlerden kaçıyorum. Ama anlatabildiğim kadarıyla bu skorda azınlıktayız.
David Arno

2
Çok üzücü görünüyor - IoC konteynerlerinin "sihirli" kampından uzaklaşırken, alaycı kütüphaneler vb. yukarı. Yine de +1.
Ant P

3
@AntP & David: 'Pure DI' kampında yalnız olmadığımı duymak güzel. Dillerdeki eksikliklerin giderilmesi için DI konteynerleri oluşturuldu. Bu anlamda değer katıyorlar. Ama bence, gerçek cevap dilleri düzeltmek (veya diğer dillere geçmek) ve onların üzerine acımasızlık yapmamaktır.
JimmyJames

1

Eski ekiplerdeki / kod tabanlarındaki paragidm değişimleri son derece risklidir:

Önerdiğiniz her an "iyileştirmeler" eski koduna ve orada "eski" takımda programcılar, sen sadece o herkese söylüyorsunuz "onlar yanlış yaptılar" ve haline Düşman şirketi ile / zamanlarının kalanı için.

Tüm tırnakları parçalamak için bir DI Framework'ü çekiç olarak kullanmak, eski kodu tüm durumlarda daha iyi hale getirecektir. Kişisel olarak da son derece risklidir.

Test durumlarında kullanılabilecek gibi en sınırlı durumlarda bile, sadece en iyi @Ignoreşekilde kırıldıklarında veya daha kötüsünden şikayet edildiklerinde en iyi şekilde işaretlenecek olan test standartlarını "standart dışı" ve "yabancı" kod haline getirecektir. eski programcılar yönetimi ile en fazla nüfuz ve "doğru" yeniden yazılmış olsun tüm bu "birim testleri boşa zaman" sadece size suçladı.

Bir iş uygulaması hattına bir DI çerçevesi, hatta "Pure DI" kavramını tanıtmak, yönetimin, ekibin ve özellikle lider geliştiricinin sponsorluğunun olmadan daha az büyük bir eski kod tabanı sadece ölüm knell olacak sizin için takımda / şirkette sosyal ve politik olarak. Bunun gibi şeyler yapmak son derece risklidir ve en kötü şekilde politik intihar olabilir.

Bağımlılık Enjeksiyonu bir sorun arayan bir çözümdür.

Yapımcıları olan herhangi bir dil, tanımı gereği ne yaptığınızı biliyorsanız ve bir kurucuyu nasıl doğru bir şekilde kullanacağınızı anlarsanız, kurallara göre bağımlılık enjeksiyonunu kullanır, bu sadece iyi bir tasarımdır.

Bağımlılık enjeksiyonu, çok küçük şeyler için sadece küçük dozlarda yararlıdır:

  • Çok fazla değişen veya statik olarak bağlı birçok alternatif uygulamaya sahip olan şeyler.

    • JDBC sürücüleri mükemmel bir örnektir.
    • Platformdan platforma değişebilen HTTP istemcileri.
    • Platforma göre değişen log sistemleri.
  • Çerçevenizdeki yapılandırma kodunda tanımlanabilen ve başlangıçta otomatik olarak bulunabilen ve program çalışırken dinamik olarak yüklenen / yeniden yüklenen yapılandırılabilir eklentilere sahip eklenti sistemleri.


10
DI için katil uygulaması birim testtir. Belirttiğiniz gibi, çoğu yazılımın tek başına çok fazla DI'ye ihtiyacı yoktur. Ancak testler de bu kodun müşterisidir, bu yüzden test edilebilirlik için tasarlamalıyız. Özellikle, bu , testlerin davranışları gözlemleyebileceği tasarımlarımıza dikiş yerleştirmek anlamına gelir . Bu süslü bir DI çerçevesi gerektirmez, ancak ilgili bağımlılıkların açık ve yerine konabilir olmasını gerektirir.
amon

4
Eğer geliştiriciler neyin değişebileceğini önceden biliyorlarsa , bu savaşın yarısı olurdu. Bir çok sözde "sabit" şeyin değiştiği uzun gelişmelerdeydim . Burada ve orada DI'yi kullanmak için prova yapmak kötü bir şey değildir. Her zaman her yerde kullanmak kargo kült programlama şaplak.
Robbie Dee

testin aşırı karmaşık hale getirilmesi, yalnızca eski haline getirilmeleri ve gelecekte güncellenmek yerine yok sayıldıkları anlamına gelecektir. Eski kodda DI yanlış bir ekonomidir. Yapmaları gereken tek şey, tüm bu "standart olmayan, kimsenin anlamadığı aşırı karmaşık kod" kod tabanına koymak için "kötü adam" yapmaktır. Uyarıldın.

4
@JarrodRoberson, bu gerçekten toksik bir ortam. İyi bir geliştiricinin temel işaretlerinden biri, geçmişte yazdıkları koda tekrar bakmaları ve "ugh, gerçekten yazdım mı? Bu çok yanlış!" Çünkü bir geliştirici olarak büyüdüler ve yeni şeyler öğrendiler. Beş yıl önce yazdıkları ve yanlış bir şey görmedikleri kodlara bakan biri bu beş yıl içinde hiçbir şey öğrenmedi. Bu yüzden, geçmişte yanlış yaptıklarını söyleyen halk size bir düşman yapar, o zaman o şirketten hızlı bir şekilde kaçar, çünkü sizi geride tutan ve sizi zayıf seviyelerine indirecek çıkmaz bir takımdır.
David Arno

1
Emin değilim kötü adam şeyler katılıyorum ama benim için bu anahtar paket servisi olan restoran birim test yapmak için DI gerekmez. Kodun daha test edilebilir hale getirilmesi için DI'nin uygulanması sadece problemin üstesinden gelmektir.
Ant P
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.