TDD deneyiminizin olumsuz tarafı nedir? Bebek adımları (testi yeşil yapmak için en basit çözüm) can sıkıcı ve işe yaramaz mı? Değersiz testler buluyor musunuz (test başlangıçta anlamlıdır ancak son uygulamada diğer test ile aynı mantığı kontrol eder) bakım kritik mi? vb.
Yukarıdaki sorular TDD deneyimim sırasında rahatsız olduğum şeyler hakkında. Bu yüzden diğer geliştiricilerin benzer duyguları olup olmadığı ve onlar hakkında ne düşündükleri ile ilgileniyorum.
TDD'nin olumsuz yanlarını açıklayan makalelere bağlantılar için minnettar oluruz (Google, olumlu ve genellikle fanatik makalelerle doludur).
"Çevik" bayrağı altında gelen her şey gibi, TDD de teoride kulağa iyi gelen bir şeydir, ancak pratikte ne kadar iyi olduğu (ve aynı zamanda çoğu "Çevik" şey gibi), bunun gibi, yanlış yapıyorsun).
TDD'nin tanımı taşa kazınmış değildir: Kent Beck gibi adamlar, tek bir kod satırından önce derleyici olmayan bir testin yazılmasını ve başarısız bir testi geçmek için her bir kod satırının yazılmasını talep eder. Ön tasarım minimaldir ve her şey testlerle sürülür. Sadece işe yaramıyor. Bu metodoloji kullanılarak geliştirilen büyük bir kurumsal uygulama gördüm ve umarım kariyerimde gördüğüm en kötü kod (çok uzakta olmayacak; ve bu, bazı yetenekli geliştiricilerin üzerinde çalışmasına rağmen). Gördüğüm kadarıyla, esas olarak işlev çağrılarının gerçekleştiğini doğrulayan, değişkenler null olduğunda ve alaycı çerçeve kapsamlı bir egzersiz (whoop-de-whoop) olduğunda istisnaların atıldığı çok sayıda kötü düşünülmüş testle sonuçlanır; üretim kodunuz bu testlere yoğun bir şekilde bağlanır ve sürekli ve kolay yeniden düzenleme hayali görünmez - aslında, kırılacağı tüm testler nedeniyle insanların kötü kodu düzeltmesi daha az olasıdır. Bu tür bir ortamda yazılım yöneticileri, daha az teste sahip iyi bir yazılıma göre başarılı testlere ve yüksek kod kapsamına sahip kötü yazılımlara sahip olmayı tercih ederler.
Tersine, insanların TDD'nin planlama aşamasının bir parçası olarak - mimari tasarımın yanı sıra testleri üst seviyede tasarlamayı ifade ettiğini duydum. Bu testler, daha fazla bilgi elde edildikçe geliştirme sırasında değişebilir, ancak dikkatle düşünülmüş ve kodun gerçekte ne yapması gerektiği konusunda iyi bir rehber sunmaktadır. Benim için bu çok mantıklı.
Hayat kısadır ve günde sadece sınırlı sayıda saat vardır. Bu yüzden zamanımızı nasıl harcadığımız hakkında seçimler yapmalıyız. Testler yazarak geçirirsek, o zaman başka bir şey yapmak için harcama yapmıyoruz. Her birimizin hem nicelik hem de nitelik açısından sonuçlarımızı en üst düzeye çıkarmak için zamanımızı en iyi nasıl harcayacağımızı değerlendirmemiz gerekiyor. Eğer insanlar test yazmak için zamanlarının yüzde ellisini harcamanın sonuçlarını maksimize ettiğini düşünürlerse, onlar için sorun değil. Bunun benim için doğru olmadığından eminim - o zaman sorunumu düşünerek geçirmeyi tercih ederim. Bunun benim için zamanımın diğer tüm kullanımlarından daha az kusurla daha iyi çözümler ürettiğinden eminim. Eksiksiz bir test takımına sahip kötü bir tasarım hala kötü bir tasarımdır.
Seibel: Pratik çalışmadan bahsetmişken, Bilgisayar Programlama Sanatı üzerine çalışmanın ortasında, dizgi sisteminizi TeX yazmak için on yıl ara verdiniz. TeX'in ilk sürümünü bilgisayardan tamamen yazdığınızı anlıyorum.
Knuth: TeX'i orijinal olarak 1977 ve '78'de yazdığımda, elbette okuryazar programlamam yoktu ama programlamayı yapılandırdım. Uzun bir kalemle büyük bir deftere yazdım. Altı ay sonra tüm projeyi tamamladıktan sonra bilgisayara yazmaya başladım. Programın yazısını 77’nin Ekim ayında yazmaya başladığım sırada, 7878'in Mart ayındaki hata ayıklama işlemini gerçekleştirdi. Bunun kodu Stanford arşivlerinde - hepsi kalemde - ve elbette geri dönüp ne olması gerektiğini öğrendiğimde bir alt rutini değiştirirdim. Bu birinci nesil bir sistemdi, bu yüzden birçok farklı mimari mümkün oldu ve bir süre onunla yaşayana ve orada ne olduğunu bilinceye kadar atılmak zorunda kaldı. Ve bu bir tavuk ve yumurta sorunuydu; yazı tipleriniz olana kadar yazı yazamadınız, ancak yazı yazana kadar yazı tipleriniz olamazdı. Ama yapılandırılmış programlama bana değişmezler fikrini verdi ve anlayabildiğim kara kutuları nasıl yapacağımı bildi. Bu yüzden nihayet hata ayıklamak zaman kod işe güven vardı. Bir şeyi test etmeden önce altı ay beklersem çok zaman kazanacağımı hissettim. Kodun neredeyse doğru olduğuna dair yeterince güvenim vardı.
Seibel: Zamandan tasarruf etmek, eksik kodu test etmek için iskele ve saplamalar oluşturmak için zaman harcamak istemediğiniz için mi?
Knuth: Doğru.
TDD ile ilgili olumsuz deneyimim ilk deneyimimdi. TDD bana kulağa hoş geliyordu, yıllardır KG yaptım ve hala aklımda dehşet vardı. Her hatayı bir yapıya dönüştürmeden önce ezmek istedim. Ne yazık ki, TDD kullanmak iyi testler yazacağınızı garanti etmez. Aslında, ilk yatkınlığım basit kod üreten basit testler yazmaktı. Birkaç soyutlama içeren gerçekten basit bir kod. Sınıf içi ile iç içe geçmiş gerçekten basit testler. Ve birkaç bin itty bitty testiniz olduğunda, çok önemli etki alanı kavramı X'i kullanmak için kodunuzu yeniden düzenlemek için yüzünü değiştirmeniz gerektiğinde daha hızlı hareket ediyormuş gibi hissetmediğinizden emin olabilirsiniz.
Işık benim için yanıyordu - TDD bir test becerisi değil. Bu bir tasarım becerisi. Sadece uygulama ile iyi, basit, uygulanabilir bir koda ve sizi yönlendiren tasarım yönlerinin sürekli farkındalığına yol açabilir. Kod kapsamı uğruna testler yazıyorsanız, kırılgan testler oluşturacaksınız. Soyutlamalarınızı tasarlamanıza yardımcı olacak testler yazıyorsanız, yukarıdan aşağıya kod yazmanın daha titiz bir yoludur. Kodu önce arayanın perspektifinden görebiliyorsunuz, bu da bir sınıfın içini dış kenarına yansıtmak yerine hayatını kolaylaştırmanızı teşvik ediyor.
TDD'nin yararlı olduğunu düşünüyorum, ancak bu konuda dogmatik değilim. Bu "değersiz testler" bakımı zorlaştırıyorsa - Silin! Testleri kodun geri kalanıyla aynı şekilde ele alıyorum. Yeniden düzenlenebilir ve işleri daha basit hale getirebilirse, o zaman yapın!
Kişisel olarak görmedim, ancak bazı yerlerde kod kapsamı ve test sayılarını takip ettiğini duydum. Metriklerin toplanması TDD'nin bir yan etkisiyse, bunu da negatif olarak görebiliyordum. 1000 kod satırını coşkuyla sileceğim ve eğer bu 20 testten vazgeçerse ve kod kapsamımı% düşürdüyse, iyi.
Burada bir uzuv çıkacağım ve acımasız bir dürüstlükle tam anlamıyla ritüel bir zaman kaybı olduğunu ilan edeceğim. (Çoğu durumda.)
TDD'yi de tartışan Birim Test üzerine bir kitap aldım ve UT'nin faydalarını kabul ederken, yaklaşık yüz saatlik TDD'yi denedikten sonra, sayısız nedenden ötürü vazgeçtim. Ben bir çeşit çapraz gönderme buradayım, ama TDD:
Başka bir endişe, TDD'yi başarılı bir şekilde yapmak için yapması gereken tartışmalı mükemmellik derecesidir. Bazıları, TDD projenin başından beri takımdaki herkes tarafından ısrarla yapılmazsa, sadece acı çekeceğiniz konusunda ısrar ediyor. Diğerleri kitapta hiç kimsenin TDD yapmadığı konusunda ısrar ediyor. Bunların ikisi de doğruysa, TDD uygulayıcılarının farkına varsınlar da farketmeseler de acı çekiyorlar.
Tabii ki, bir şeyleri TDD benzeri bir şekilde yaparak, TDD ile kolayca çalışabilecek tasarımlara geleceğiniz tartışılıyorsa, bunu başarmanın çok daha hızlı yolları vardır - yani, aslında kavramlarını inceleyerek Birleştirmeyi. Dışarıda bol miktarda kaynak var, çok fazla titiz matematiksel teori bile (büyük ölçüde fonksiyonel programlamada değil, diğer alanlarda da). Neden tüm TDD zamanınızı öğrenmeye harcamıyorsunuz ?
Kültürel olarak TDD, ritüel bir uygulama belirtileri gösterir. Suçluluk üzerine sürüyor; anlama prosedürünü teşvik eder; tonlarca doktrin ve sloganı vardır (nesnel olarak bakarsanız "sahte yapın" gerçekten çok endişe vericidir). Wikipedia'nın "ritüel" kelimesinin tanımı aslında oldukça uygun:
Psikolojide, ritüel terimi bazen teknik anlamda bir kişi tarafından kaygıyı nötralize etmek veya önlemek için sistematik olarak kullanılan tekrarlayan bir davranış için kullanılır; obsesif-kompulsif bozukluğun bir belirtisidir.
Eklemek için, TDD ile fark ettiğim bir başka endişe:
TDD, yanlışlıkla Kalite Kodundan Testcases'a ve Kod Kapsamına geliştirme ekibinin odağında kayma neden olur! Şahsen TDD'yi beğenmedim beni daha az yaratıcı ve yazılım geliştirmeyi donuk bir mekanik süreç haline getiriyor! Birim test senaryoları, mantıklı bir şekilde kullanıldığında yararlıdır, ancak yazılım geliştirme hedefi ele alındığında bir yük haline gelir.
Yönetici olan ve teknik olarak donuk olan bir adamı tanıyorum, bir zamanlar TDD'ye takıntılıydı. Onun için o kadar büyülü bir şeydi ki, kötü yapılandırılmış yazılımındaki en az sürdürülebilir kodla tüm sorunlara büyülü çözümler getireceğine inanıyordu. Bu projeye ne olduğunu söylememek, tüm testisleri yeşilken ellerinde sefil bir şekilde başarısız oldu. Sanırım TDD, "Vakalarımın 99/100'ü yeşil" vb.
Birincil olumsuz deneyimim, testleri olmayan veya çok, çok temel entegrasyon testlerine sahip başka bir programcının kodunu düzenlemek için TDD'yi kullanmaya çalışıyor. Bir özellik eklemek veya adı geçen kod ile ilgili bir sorunu gidermek; Önce bir test yazmayı tercih ederim (TDD yolu). Ne yazık ki, kod sıkıca bağlı ve hiçbir şey yeniden düzenleme olmadan test edemez.
Yeniden düzenleme yine de harika bir alıştırmadır, ancak kodu test edilebilir bir duruma sokmak zorunl. Ve bu adımdan sonra, değişikliklerimin bir şey yapıp yapmadığını görmek için hiçbir kontrolüm ve bakiyem yok; uygulamayı çalıştırma ve her kullanım durumunu inceleme eksikliği.
Öte yandan, bir TDD projesine özelliklerin eklenmesi/hataların düzeltilmesi çok basit hale gelir. Doğası gereği, TDD ile yazılan kod genellikle çalışmak için küçük parçalarla oldukça ayrıştırılır.
Her durumda, TDD bir kılavuzdur. Maksimum verimlilik elde ettiğiniz noktaya kadar takip edin. İyi test kapsamı ve ayrıştırılmış kod, iyi yazılmış kod.
Sistemin tasarımı söz konusu olduğunda bazen testlerime çok fazla güvendiğim deneyimi yaşadım. Ben daha büyük resme bakmak için geri adım atmak için nitrit cesur uygulama ayrıntıları temelde çok düşük. Bu genellikle gereksiz karmaşık bir tasarıma neden olur. Biliyorum, kodu yeniden düzenlemem gerekiyor ama bazen daha sık adım geri alarak çok zaman kazandırabilirim izlenim var.
Bununla birlikte, Rails gibi mimari kararlarınızın çok sınırlı olduğu bir çerçeveniz varsa, bu sorunlar temelde mevcut değildir.
Başka bir sorun da testlerinize körü körüne güvenmenizdir. Gerçek şu ki - diğer kodlar gibi - testlerinizde de hatalar olabilir. Bu yüzden testleriniz için uygulamanız kadar kritik olun.
TDD'nin büyük bir hayranı olarak bazen bu dezavantajları görüyorum
Test kodunun bakım maliyetleri sadece biraz değişiklik gösteren benzer testler için (kod çoğaltma (diğer adıyla kopyala-yapıştır-kalıtım)). Zaten bir tane varsa, benzer bir tane oluşturmak kolaydır. Ancak, test kodunu yeniden düzenlemezseniz, yardımcı yöntemlere kod çoğaltmayı ortadan kaldırarak, iş kodunuzun uygulama ayrıntıları değişirse testleri düzeltmek için biraz zamana ihtiyacınız olabilir.
zaman baskısı altındaysanız, kırık testleri ortadan kaldırın (veya yorum yapın) düzeltmek yerine onlara cazip gelebilirsiniz. Bu şekilde testlere yatırımınızı kaybedersiniz
TDD'nin değerli olduğu bir oyun geliştiricisi olarak henüz birden fazla senaryo ile karşılaşmadım. Ve içinde bulunduğu örnek, doğada tamamen matematiksel olan ve çok sayıda Edge vakasını aynı anda test etmek için sağlam bir yaklaşıma ihtiyaç duyan bir kod parçasıydı - nadir bir ihtiyaç.
Belki bir şey, bir gün fikrimi değiştirecek, ancak XP uygulamalar arasında, acımasızca yeniden düzenleme fikri ve kod arasında gelişmekte olan kendi formu çok daha önemlidir ve benim için en büyük üretkenliğe yol açar, bkz. James Newkirk'in makalesi :
Basitlik - "Muhtemelen işe yarayabilecek en basit şey nedir?"
Mesaj çok açık. Bugünün gereksinimleri göz önüne alındığında, yazılımınızı tasarlayın ve yazın. Geleceği tahmin etmeye çalışmayın, geleceğin gelişmesine izin verin. Bunu genellikle öngörülemeyen şekillerde yapar, bu beklentiyi karşılayamayacak kadar pahalı bir maliyet haline getirir. "
Ayrıca bahsettiği cesaret ve sıkma geri besleme kavramları , bence, üretkenliğin anahtarı.
Olumsuz TDD deneyimim, sınırlı olabileceği gibi, nereden başlayacağımı bilmektir! Örneğin, bir şey TDD yapmaya çalışacağım ve ya önemsiz şeyleri test etmeye nasıl başlayacağımı bilmiyorum (bir
Foo nesnesini yenileyebilir miyim, bir
Quux
Baz ve benzerleri. Hiçbir şeyi test etmeyen testler) veya mevcut bir projeye uygulamaya çalışıyorsam, bunları kullanabilmek için çeşitli sınıfları yeniden yazmak zorunda kalacağım. TDD. Sonuç olarak kavramı çabucak tamamen terk ettim.
Muhtemelen, şirket genelinde birim testin (TDD ya da başka bir şekilde) ne olduğunu ve neden iyi bir şey olduğunu bilen tek kişi olduğuma yardımcı olmuyor.
Benim için, onlar benim kapımı çaldı uzun bir dini loonies hattı sadece biridir, bir şeyler yapma yolumun tamir edilemez bir şekilde kırık olduğunu kanıtlamak için çalışıyor ve kurtuluş için tek yol İsa, Kent Back veya Birim Test olduğunu.
Ve TDD kullanarak değil, eski moda mühendislik kullanarak yapılan Peter Norvig sudoku çözücü ile karşılaştırın: http://norvig.com/sudoku.html
Bu "fanatik" makalelerden TDD kullanırsanız, yazılımınızın hiçbir hatası olmadığını yanlış güvenlik hissi alırsınız.
TDD'nin bazı faydaları vardır:
TDD uzun vadeli bir yatırımdır. Uygulamanızın bakım moduna eriştiğinizde bu çaba işe yarar ve uygulama bu noktaya ulaşması planlanmadıysa yatırımı asla geri kazanamazsınız.
TDD kırmızı-yeşil döngüsünü, bebek adımlarını bir uçak için bir kontrol listesine benzer şekilde düşünüyorum. Özellikle önemsiz derecede basitse (TDD bebeği adımları) kalkıştan önce uçaktaki her şeyi kontrol etmek can sıkıcı ve sıkıcıdır, ancak güvenliği arttırdığı bulunmuştur. Her şeyin işe yaradığını doğrulamanın yanı sıra, temel olarak uçağı sıfırlar . Başka bir deyişle, her kalkıştan önce bir uçak yeniden başlatılır.
Birden fazla vesileyle, ertesi gün sakar olduğu için attığım kod yazdım. TDD ile yeniden başladım ve çözüm daha iyiydi. Dolayısıyla, olumsuz TDD deneyimi doğrultusunda çok fazla şey yaşamadım. Bununla birlikte, bir sorun hakkında düşünmek ve TDD alanı dışında daha iyi bir çözüm bulmak için zaman harcadım.
Yeni sistemler söz konusu olduğunda TDD'nin kötü performans gösterdiğini gördüm. Ben bir video oyunları geliştiricisiyim ve son zamanlarda TDD'yi bir varlık için gerçekçi görünümlü hareketler oluşturmak için birden fazla basit davranış kullanan bir sistem oluşturmak için kullandım.
Örneğin, sizi farklı türlerdeki tehlikeli alanlardan uzaklaştırmaktan ve sizi farklı türlerdeki ilginç alanlara taşımaktan sorumlu davranışlar vardır. Her davranışın çıktısını birleştirmek son bir hareket yaratır.
Sistemin bağırsakları kolayca uygulandı ve TDD burada her alt sistemin neyin sorumlu olması gerektiğini belirtmek için yararlı oldu.
Bununla birlikte, davranışların nasıl etkileşime girdiğini ve daha da önemlisi zamanla nasıl etkileştiklerini belirleme konusunda sorunlarla karşılaştım. Çoğu zaman doğru bir yanıt yoktu ve ilk testlerim geçmesine rağmen, KG sistemin çalışmadığı Edge vakalarını bulmaya devam edebilirdi. Doğru çözümü bulmak için birkaç farklı davranışı yinelemek zorunda kaldım ve testleri her seferinde yeni davranışları yansıtmak için oyun içinde çalıştıklarını yansıtacak şekilde güncellersem, testleri tekrar tekrar atmış olabilirim. Bu testleri sildim.
Muhtemelen QA'nın keşfettiği Edge vakalarını yakalayan daha güçlü testler yapmalıydım, ancak birçok fizik ve oyun sisteminin üstünde duran böyle bir sisteminiz olduğunda, ve zamanla davranışlarla uğraşıyorsunuz , tam olarak ne olduğunu belirtmek kabus olur.
Neredeyse kesinlikle yaklaşımımda hatalar yaptım ve söylediğim gibi sistemin cesaretini karşılayan TDD mükemmel bir şekilde çalıştı ve hatta birkaç optimize ediciyi destekledi.
TDD hakkındaki olumsuz deneyimim, birçok yeni ve hiper şeyle hissettiğim bir şey. Aslında benim kod geçerliliği sağlar TDD zevk, ve daha da önemlisi: Yeni kod veya herhangi bir tür yeniden düzenleme ekledikten sonra, başarısız testleri tanıyabilir.
TDD hakkında beni rahatsız eden şey, bununla ilgili birçok kural veya yönerge olması. Hâlâ oldukça yeni olduğu için, çoğumuz TDD'de yeni başlayanlar olarak deneyimliyoruz. Bu yüzden bazılarımız için iyi olan, başkaları için işe yaramayabilir. Söylemek istediğim, TDD'yi gerçekleştirmek için gerçek bir "yanlış veya doğru" yolun olmaması: Benim için ve benim takımım varsa işe yarayan yol var.
Testler yazdığınız sürece - üretim kodundan önce veya sonra IMHO gerçekten önemli değil - test sürüşünün gerçekten şu anda belirtilen tüm yönergelere uymanız gerektiği anlamına gelmediğinden emin değilim, çünkü henüz kanıtlanmış değiller günlük işler için ideal çözüm. Test yazmanın daha iyi bir yolunu bulursanız, bunu bir blogda yayınlamalı, burada tartışmalı veya bunun hakkında bir makale yazmalısınız. Bu nedenle, on yıl içinde, TDD'nin hangi kuralının belirli bir durumda iyi olduğunu ya da olmadığını varsayabilecek kadar tecrübe paylaşmış olabiliriz.