Test odaklı tasarımı benimseyerek ne kaybederim?
Yalnızca negatifleri listeleyin; olumsuz formda yazılan faydaları listelemeyin.
Test odaklı tasarımı benimseyerek ne kaybederim?
Yalnızca negatifleri listeleyin; olumsuz formda yazılan faydaları listelemeyin.
Yanıtlar:
Birkaç dezavantajı (ve hiçbir faydası olduğunu iddia etmiyorum - özellikle bir projenin temelini yazarken - sonunda çok zaman kazandıracak):
"Gerçek" TDD yapmak istiyorsanız (okuma: önce kırmızı, yeşil, refactor adımlarıyla test edin), entegrasyon noktalarını test etmek istediğinizde ayrıca alayları / saplamaları kullanmaya başlamanız gerekir.
Alayları kullanmaya başladığınızda, bir süre sonra Bağımlılık Enjeksiyonu (DI) ve Bir Ters Çevirme (IoC) kabı kullanmaya başlamak istersiniz. Bunu yapmak için her şey için arayüzler kullanmanız gerekir (çok fazla tuzakları vardır).
Günün sonunda, sadece "düz eski yol" yapmak yerine, çok daha fazla kod yazmak zorunda. Sadece bir müşteri sınıfı yerine, bir arayüz, sahte bir sınıf, bazı IoC yapılandırması ve birkaç test yazmanız gerekir.
Ve test kodunun da korunması ve bakımının yapılması gerektiğini unutmayın. Testler diğer her şey gibi okunabilir olmalı ve iyi kod yazılması zaman alacaktır.
Birçok geliştirici, tüm bunların "doğru" şekilde nasıl yapılacağını tam olarak anlamamaktadır. Ancak herkes onlara TDD'nin yazılım geliştirmenin tek gerçek yolu olduğunu söylediğinden, ellerinden gelenin en iyisini yapmaya çalışıyorlar.
Birinin düşündüğünden çok daha zor. Genellikle TDD ile yapılan projeler, kimsenin gerçekten anlamadığı birçok kodla sonuçlanır. Birim testleri genellikle yanlış olanı, yanlış yolu test eder. Ve hiç kimse iyi bir testin nasıl olması gerektiğini kabul etmez, sözde guruları bile.
Tüm bu testler, sisteminizin davranışını (yeniden düzenlemenin tersine) "değiştirmeyi" zorlaştırır ve basit değişiklikler çok zor ve zaman alıcı hale gelir.
TDD literatürünü okursanız, her zaman çok iyi örnekler vardır, ancak çoğu zaman gerçek yaşam uygulamalarında bir kullanıcı arayüzünüz ve bir veritabanınız olmalıdır. TDD gerçekten zorlaşıyor ve çoğu kaynak iyi cevaplar vermiyor. Ve eğer yaparlarsa, her zaman daha fazla soyutlama içerir: sahte nesneler, bir arayüze programlama, MVC / MVP kalıpları vb., Yine çok fazla bilgi gerektirir ve ... daha fazla kod yazmanız gerekir.
Bu yüzden dikkatli olun ... hevesli bir ekibiniz ve iyi testler yazmayı bilen ve aynı zamanda iyi mimari hakkında birkaç şey bilen en az bir deneyimli geliştiriciniz yoksa, TDD yoluna çıkmadan önce iki kez düşünmeniz gerekir. .
Çok sayıda testinizin olduğu noktaya geldiğinizde, sistemi değiştirmek, hangilerinin değişikliklerin geçersiz kıldığına bağlı olarak, testlerinizin bir kısmını veya tamamını yeniden yazmanızı gerektirebilir. Bu, nispeten hızlı bir değişikliği çok zaman alan bir modifikasyona dönüştürebilir.
Ayrıca, aslında iyi tasarım prensiplerinden ziyade TDD'ye dayalı tasarım kararları almaya başlayabilirsiniz. TDD'nin talep ettiği yöntemi test etmek imkansız olan çok basit ve kolay bir çözüme sahip olsanız da, artık aslında hatalara daha yatkın çok daha karmaşık bir sisteminiz var.
if part of the system is covered by tests and they pass, then everything is fine (including design)
.
Benim için en büyük sorun "içine almak" alır BÜYÜK zaman kaybı olduğunu düşünüyorum. TDD ile yolculuğumun başlangıcında hala çoktayım ( ilgileniyorsanız test maceralarımın güncellemeleri için bloguma bakın ) ve tam anlamıyla saatlerce başladım.
Beyninizi "test moduna" sokmak ve "test edilebilir kod" yazmak başlı başına bir beceridir.
TBH, Jason Cohen'in özel yöntemleri herkese açık hale getirme hakkındaki yorumlarına saygıyla katılmıyorum , bununla ilgili değil. Yeni çalışma şeklimde öncekinden daha fazla kamusal yöntem yapmadım . Bununla birlikte, mimari değişiklikleri içerir ve diğer her şeyi test etmeyi kolaylaştırmak için kod modüllerini "çalışırken takmanıza" izin verir. Sen gerektiğini değil bunu yapmak için kodunuzu internal'leri daha erişilebilir hale edilebilir. Aksi takdirde, her şeyin halka açık olduğu bir kareye geri dönüyoruz, içindeki kapsülleme nerede?
Yani, (IMO) kısaca:
Not: Olumlu bağlantılar istiyorsanız, birkaç soru sordum ve cevapladım, profilime göz atın .
Teste Dayalı Geliştirme uyguladığım birkaç yıl içinde, en büyük dezavantajları:
TDD en iyi çiftler halinde yapılır. Birincisi, bir if / else deyiminin nasıl yazılacağını Bildiğinizde sadece uygulamayı yazma dürtüsüne direnmek zor . Ama bir çift seni görevde tutacak çünkü onu görevde tutuyorsun. Ne yazık ki, birçok şirket / yönetici bunun kaynakların iyi bir kullanımı olduğunu düşünmüyor. Aynı anda yapılması gereken iki özelliğim olduğunda neden iki kişinin bir özellik yazması için ödeme yapmalıyım?
Bazı insanlar sadece birim test yazma konusunda sabra sahip değildir. Bazıları çalışmaları ile gurur duyuyor. Ya da bazıları kıvrık yöntemlerin / fonksiyonların ekranın sonundan aktığını görmek gibi. TDD herkes için değil, ama keşke gerçekten olsaydı. Kodu miras alan fakir ruhlar için işleri sürdürmeyi çok daha kolay hale getirir.
İdeal olarak, testleriniz yalnızca kötü kod kararı aldığınızda kırılır. Yani, sistemin bir şekilde çalıştığını düşündünüz ve öyle olmadı. Bir testi veya (küçük) bir test setini kırarak, bu aslında iyi bir haberdir. Yeni kodunuzun sistemi nasıl etkileyeceğini tam olarak biliyorsunuz . Bununla birlikte, testleriniz kötü yazılmışsa, sıkıca bağlanmışsa veya daha da kötüsü ( öksürük VS Testi) üretilmişse , testlerinizi sürdürmek hızlı bir şekilde koro haline gelebilir. Ve, yeterli testler yarattıkları algılanan değere göre daha fazla çalışmaya neden olduktan sonra, programlar zamanlamalar sıkıştırıldığında ilk silinecek olan şey olacaktır (örn. Zamana çarpıyor)
İdeal olarak, yine, metodolojiye bağlı kalırsanız, kodunuz varsayılan olarak% 100 test edilecektir. Tipik olarak, düşündüm,% 90 yukarı kod kapsamı ile sonunda. Bu genellikle bazı şablon tarzı mimariye sahip olduğumda ve taban test edildiğinde olur ve köşeleri kesmeye çalışır ve şablon özelleştirmelerini test etmemeye çalışırım. Ayrıca, daha önce karşılaşmadığım yeni bir engelle karşılaştığımda, bunu test etmede bir öğrenme eğrisim olduğunu gördüm. Bazı kod satırlarını eski skool yoluna yazmayı kabul edeceğim, ancak% 100'üne sahip olmayı gerçekten çok seviyorum. (Sanırım okulda aşırı başarılıydım, er skool).
Bununla birlikte, TDD'nin faydalarının, başvurunuzu kapsayan iyi bir test seti elde edebileceğiniz, ancak bir değişikliğin hepsini kıracağı kadar kırılgan olmadığı basit bir fikrin olumsuzluklarından çok daha ağır bastığını söyleyebilirim. 1. günde yaptığınız gibi projenizin 300. gününde yeni özellikler eklemeye devam edebileceksiniz. Bu, TDD'yi deneyen herkesin hata kodlu tüm kodları için sihirli bir kurşun olduğunu düşünerek gerçekleşmez ve bu yüzden iş değil, nokta.
Şahsen TDD ile, daha basit bir kod yazıyorum, belirli bir kod çözümünün işe yarayıp yaramayacağını tartışmak için daha az zaman harcadığımı ve ortaya koyduğu kriterleri karşılamayan herhangi bir kod satırını değiştirme korkum olmadığını buldum takım.
TDD, ustalaşması zor bir disiplindir ve birkaç yıldır buradayım ve hala yeni test tekniklerini öğreniyorum. Önde büyük bir zaman yatırımıdır, ancak uzun vadede sürdürülebilirliğiniz, otomatik birim testlerinizden çok daha büyük olacaktır. Şimdi, sadece patronlarım bunu çözebilseydi.
İlk TDD projenizde iki büyük kayıp var: zaman ve kişisel özgürlük
Zaman kaybedersiniz çünkü:
Kişisel özgürlüğü kaybedersiniz çünkü:
Bu yardımcı olur umarım
TDD, bu testleri geçmek için kod yazmadan önce sınıflarınızın nasıl çalışacağını planlamanızı gerektirir. Bu hem artı hem de eksi.
Herhangi bir kod yazılmadan önce bir "vakum" test yazmak zor buluyorum. Deneyimlerime göre, derslerimi yazarken kaçınılmaz olarak bir şey düşündüğümde, ilk testlerimi yazarken unuttuğum sınavlarım üzerinde gezme eğilimindeyim. O zaman sadece sınıflarımı yeniden düzenleme zamanı değil, aynı zamanda sınavlarımı da yeniden düzenleme zamanı. Bunu üç veya dört kez tekrarlayın ve sinir bozucu olabilir.
Önce sınıflarımın bir taslağını yazmayı, daha sonra bir birim test pili yazmayı (ve sürdürmeyi) tercih ederim. Bir taslak hazırladıktan sonra, TDD benim için iyi çalışıyor. Örneğin, bir hata rapor edilirse, bu hatadan yararlanmak için bir test yazacağım ve daha sonra testin geçmesi için kodu düzeltecağım.
Prototip oluşturmak TDD ile çok zor olabilir - bir çözüme hangi yolu seçeceğinizden emin değilseniz, testleri ön tarafa yazmak zor olabilir (çok geniş olanlar dışında). Bu bir acı olabilir.
Dürüst olmak gerekirse, projelerin büyük çoğunluğu için "çekirdek geliştirme" için herhangi bir gerçek dezavantajı olduğunu düşünmüyorum; olması gerekenden çok daha fazla konuşulur, genellikle kodlarının testlere ihtiyaç duymayacak kadar iyi olduğuna inanan insanlar (asla değildir) ve sadece düz olan insanlar bunları yazmak için rahatsız edilemezler.
Ve bu esneme, testlerinizin hatalarını ayıklamanız gerekiyor. Ayrıca, testlerin yazılması için belirli bir maliyet vardır, ancak çoğu insan, hem kullanım ömrü boyunca hem de hata ayıklamadan ve kararlılıktan tasarruf ederek uygulamanın ömrü boyunca ödeme yapan bir ön yatırım olduğunu kabul eder.
Bununla birlikte, kişisel olarak yaşadığım en büyük sorun, testleri gerçekten yazmak için disipline girmek. Bir ekipte, özellikle yerleşik bir ekipte, onları harcanan zamanın değerli olduğuna ikna etmek zor olabilir.
Testleriniz çok kapsamlı değilse, sadece testlerin geçmesi nedeniyle yanlış bir "her şey işe yarar" hissine düşebilirsiniz. Teorik olarak testleriniz başarılı olursa kod çalışır; ama ilk defa mükemmel kod yazabilseydik testlere ihtiyacımız olmazdı. Buradaki ahlaki, tam bir şey çağırmadan önce kendi başına bir sağlık kontrolü yaptığınızdan emin olmaktır, sadece testlere güvenmeyin.
Bu notta, akıl sağlığı kontrolünüz test edilmeyen bir şey bulursa, geri dönüp bunun için bir test yazdığınızdan emin olun.
TDD için olumsuz genellikle sıkıca yerleştirir 'Çevik' metodolojisi ile ilişkili olmasıdır hiçbir bir test sadece geliştirici yıllarda başka kahntılannin ziyade belirli bir değeri döndürür 'gerektiğini' niçin bir sistem, daha doğrusu anlayış arkasında dökümanlarına önemini kafası.
Geliştirici, testin başka bir değer değil, belirli bir değer döndürme nedenini terk eder veya unutur etmez, mahvolursunuz. TDD, dünyanın değiştiği ve uygulamanızın da ihtiyaç duyduğu 5 yıl içinde atıfta bulunulabilen, insan tarafından okunabilir (örn. Sivri saçlı yönetici) belgelerle yeterince belgelenir ve çevrelenirse iyidir.
Belgelerden bahsettiğimde, bu kodda bir bulanıklık değil, bu, uygulama dışında mevcut olan, yöneticiler, avukatlar ve güncelleme yapmak zorunda olan fakir sap tarafından atıfta bulunulabilecek kullanım durumları ve arka plan bilgileri gibi resmi yazıdır. 2011 yılında kodunuzu girin.
TDD'nin beni deli ettiği birçok durumla karşılaştım. Bazılarını adlandırmak için:
Test senaryosunun sürdürülebilirliği:
Büyük bir işletmedeyseniz, test senaryolarını kendiniz yazmak zorunda kalmamanız veya en azından şirkete girdiğinizde en azından bir başkası tarafından yazılması gerekmez. Bir uygulamanın özellikleri zaman zaman değişir ve HP Quality Center gibi bir sisteminiz yoksa bunları takip etmek için hiçbir zaman delirmezsiniz.
Bu aynı zamanda yeni ekip üyelerine test senaryolarında neler olup bittiğini yakalamak için oldukça fazla zaman harcayacağı anlamına geliyor. Buna karşılık, bu daha fazla paraya çevrilebilir.
Test otomasyon karmaşıklığı:
Test senaryolarının bir kısmını veya tamamını makineyle çalıştırılabilen test komut dosyalarına otomatik hale getirirseniz, bu test komut dosyalarının ilgili manuel test senaryolarıyla senkronize olduğundan ve uygulama değişiklikleriyle uyumlu olduğundan emin olmanız gerekir.
Ayrıca, hataları yakalamanıza yardımcı olan kodların hatalarını ayıklamak için zaman harcarsınız. Benim düşünceme göre, bu hataların çoğu test ekibinin otomasyon testi komut dosyasındaki uygulama değişikliklerini yansıtmamasından kaynaklanmaktadır. İş mantığı, GUI ve diğer dahili öğelerde yapılan değişiklikler, komut dosyalarınızın çalışmamasını veya güvenilmez bir şekilde çalışmasını durdurabilir. Bazen değişiklikler çok incedir ve tespit edilmesi zordur. Komut dosyalarımın tümü, bir kez tablo 1'den tablo 2 iken hesaplarını tablo 1'den aldıkları için hata bildirdiler (çünkü biri uygulama kodundaki tablo nesnelerinin adını değiştirdi).
En büyük sorun, uygun birim testlerini nasıl yazacağını bilmeyen kişilerdir. Birbirine bağlı testler yazıyorlar (ve Ant ile harika çalışıyorlar, ancak sonra Eclipse'den çalıştırdığımda aniden başarısız oluyorlar, çünkü sadece farklı sırayla çalışıyorlar). Özellikle hiçbir şeyi test etmeyen testler yazıyorlar - sadece kodda hata ayıklıyorlar, sonucu kontrol ediyorlar ve teste dönüştürüyorlar ve "test1" diyorlar. Sınıflar ve yöntemlerin kapsamını genişletirler, çünkü onlar için birim testleri yazmak daha kolay olacaktır. Tüm klasik programlama problemleri (ağır kuplaj, 500 satır uzunluğunda yöntemler, sabit kodlanmış değerler, kod çoğaltma) ile birlikte birim testleri kodu korkunçtur ve sürdürülmesi cehennemdir. Bazı tuhaf nedenlerle insanlar birim testlerini "gerçek" koddan daha aşağı bir şey olarak görürler ve t Kalitelerini hiç umursamıyorum. :-(
Test yazmak için çok fazla zaman kaybedersiniz. Tabii ki, bu, hataları daha hızlı yakalayarak projenin sonunda kurtarılabilir.
En büyük dezavantajı, eğer gerçekten TDD'yi düzgün yapmak istiyorsanız, başarılı olmadan önce çok başarısız olmanız gerekecek. Kaç yazılım şirketinin çalıştığı göz önüne alındığında (KLOC başına dolar) sonunda işten çıkarılacaksınız. Kodunuz daha hızlı, daha temiz, bakımı daha kolay ve daha az hata olsa bile.
Size KLOC'lar tarafından ödeme yapan bir şirkette çalışıyorsanız (veya uygulanan şartlar - test edilmese bile) TDD'den (veya kod incelemeleri veya çift programlama veya Sürekli Entegrasyon vb.) Uzak durun.
Tüm kodunuzu test etmeden önce "bittiğini" söyleme yeteneğini kaybedersiniz.
Çalıştırmadan önce yüzlerce veya binlerce satır yazma yeteneğini kaybedersiniz.
Hata ayıklama yoluyla öğrenme fırsatını kaybedersiniz.
Emin olmadığınız kodu gönderme esnekliğini kaybedersiniz.
Modüllerinizi sıkıca bağlama özgürlüğünü kaybedersiniz.
Düşük seviyeli tasarım dokümantasyonu yazmayı atlama seçeneğini kaybedersiniz.
Herkesin değişmekten korktuğu kodla gelen istikrarı kaybedersiniz.
İlk geliştirme zamanı ile ilgili cevabı ikinci olarak verdim. Ayrıca, testlerin güvenliği olmadan uygun şekilde çalışma yeteneğini de kaybedersiniz. Ayrıca bir TDD nutbar olarak da tanımlandım, böylece birkaç arkadaşınızı kaybedebilirsiniz;)
Zor, öngörülemeyen gereksinimlere yeniden odaklanmak, programcının sürekli sorunudur. Test odaklı geliştirme, sizi zaten bilinen, sıradan gereksinimlere odaklanmaya zorlar ve gelişiminizi önceden hayal edilenle sınırlar.
Bir düşünün, muhtemelen belirli test senaryoları için tasarım yapmanız muhtemeldir, böylece yaratıcı olmayacak ve "kullanıcı X, Y ve Z yapabilseydi iyi olur" diye düşünmeye başlamayacaksınız. Bu nedenle, bu kullanıcı potansiyel serin gereksinimler X, Y ve Z hakkında heyecanlanmaya başladığında, tasarımınız önceden belirlenmiş test senaryolarına çok katı bir şekilde odaklanmış olabilir ve ayarlanması zor olacaktır.
Bu, elbette, iki ucu keskin bir kılıçtır. Tüm zamanınızı, bir kullanıcının isteyebileceği her akla gelebilecek, akla gelebilecek X, Y ve Z için tasarlayarak harcarsanız, kaçınılmaz olarak hiçbir şeyi tamamlamazsınız. Bir şeyi tamamlarsanız, (kendiniz de dahil) herkesin kodunuzda / tasarımınızda ne yaptığınıza dair herhangi bir fikre sahip olması imkansız olacaktır.
XML beslemeleri ve veritabanları gibi "rastgele" veriler için zor ve zaman alıcı yazma testleri olabilir (o kadar da zor değil). Son zamanlarda hava durumu veri feed'leriyle çalışmak için biraz zaman geçirdim. Bunun için yazma testleri oldukça kafa karıştırıcı, en azından TDD ile çok fazla deneyimim yok.
Birden fazla sorumluluğu olan büyük sınıfları kaybedeceksiniz. Ayrıca, büyük sorumlulukları olan büyük yöntemleri de kaybedersiniz. Refactor yeteneğini kaybedebilirsiniz, ancak refactor ihtiyacını da kaybedersiniz.
Jason Cohen şöyle bir şey söyledi: TDD kodunuz için belirli bir organizasyon gerektirir. Bu mimari olarak yanlış olabilir; örneğin, özel yöntemler bir sınıfın dışında çağrılamayacağından, bunları test edilebilir yapmak için özel olmayan yöntemler yapmanız gerekir.
Bunun kaçırılmış bir soyutlamayı gösterdiğini söylüyorum - özel kod gerçekten test edilmesi gerekiyorsa, muhtemelen ayrı bir sınıfta olmalıdır.
Dave Mann
Uygulamaları farklı bir şekilde yazmalısınız: bunları test edilebilir kılar. İlk başta bunun ne kadar zor olduğuna şaşıracaksınız.
Bazı insanlar çok zor yazmadan önce ne yazacaklarını düşünme kavramını bulurlar. Alay etmek gibi kavramlar bazıları için zor olabilir. Eski uygulamalardaki TDD, test için tasarlanmamışlarsa çok zor olabilir. TDD dostu olmayan çerçevelerin etrafında TDD de bir mücadele olabilir.
TDD bir beceridir, bu nedenle genç geliştiriciler ilk başta mücadele edebilirler (esas olarak bu şekilde çalışmaları öğretilmediği için).
Genel olarak insanlar yetenekli hale gelir ve böylece 'koklamak' kodu soyutlama ve daha istikrarlı bir sistem var eksilerini çözüldü.
İyi cevaplar. TDD'nin karanlık tarafını önlemek için birkaç yol ekleyeceğim:
Kendi rastgele testlerini yapmak için uygulamalar yazdım. Belirli testler yazmayla ilgili sorun, birçoğunu yazsanız bile, sadece düşündüğünüz vakaları kapsar. Rastgele test jeneratörleri aklınıza gelmeyen problemleri bulur.
Çok sayıda birim testi kavramı, karmaşık veri yapıları gibi geçersiz durumlara girebilecek bileşenlere sahip olduğunuz anlamına gelir. Karmaşık veri yapılarından uzak durursanız test edilecek çok daha az şey vardır.
Uygulamanızın izin verdiği ölçüde, bildirimlerin, olayların ve yan etkilerin doğru sıralanmasına dayanan tasarımdan utangaç olun. Bunlar kolayca düşebilir veya karıştırılabilir, böylece çok fazla teste ihtiyaç duyarlar.
TDD, kodunuz için belirli bir organizasyon gerektirir. Bu verimsiz veya okunması zor olabilir. Hatta mimari olarak yanlış; örneğin,private
yöntemler bir sınıfın dışında çağrılamayacağından, bunları test edilebilir yapmak için özel olmayan yöntemler yapmanız gerekir, bu da yanlıştır.
Kod değiştiğinde, testleri de değiştirmeniz gerekir. Yeniden düzenleme ile bu çok fazladan iş olabilir.
Bir TDD projesine BDD ilkelerini uygularsanız, burada listelenen bazı önemli dezavantajları (karışıklık, yanlış anlama vb.) Azaltabileceğinizi de ekleyeyim. BDD'ye aşina değilseniz, Dan North'un tanıtımını okumalısınız. İşyerinde TDD uygulamaktan kaynaklanan bazı sorunlara cevap olarak bu kavramı ortaya attı. Dan'ın BDD'ye girişini burada bulabilirsiniz .
Bunu sadece öneriyorum çünkü BDD bu olumsuzlukların bazılarını ele alıyor ve boşluk bırakıyor. Geri bildiriminizi toplarken bunu dikkate almak istersiniz.
Testlerinizin her zaman güncel olduğundan emin olmalısınız, kırmızı ışıkları görmezden gelmeye başladığınız an, testlerin anlamsız hale geldiği andır.
Ayrıca testlerin kapsamlı olduğundan emin olmalısınız, ya da büyük bir hata ortaya çıktığında, nihayetinde daha fazla kod yazarak zaman harcamanıza izin verdiğiniz havasız yönetim türü şikayet edecektir.
Ekibimin çevik gelişimini öğreten kişi planlamaya inanmadı, sadece en küçük gereksinim için yazdınız.
Sloganı refactor, refactor, refactor idi. Refactor'un 'önceden planlama yapmak' anlamına geldiğini anladım.
Geliştirme süresi artar: Her yöntemin test edilmesi gerekir ve bağımlılıkları olan büyük bir uygulamanız varsa verilerinizi testler için hazırlamanız ve temizlemeniz gerekir.