Apa sisi negatif dari pengalaman TDD Anda? Apakah Anda menemukan langkah bayi (perbaikan paling sederhana untuk membuat tes hijau) mengganggu dan tidak berguna? Apakah Anda menemukan tes tidak-bernilai (ketika tes awalnya masuk akal tetapi dalam implementasi akhir memeriksa logika yang sama dengan tes lainnya) tetap penting? dll.
Pertanyaan di atas adalah tentang hal-hal yang saya merasa tidak nyaman selama pengalaman TDD saya. Jadi saya tertarik apakah pengembang lain memiliki perasaan yang sama dan apa yang mereka pikirkan tentang mereka.
Akan berterima kasih atas tautan ke artikel yang menggambarkan sisi negatif TDD (Google dipenuhi oleh artikel positif dan sering fanatik).
Jawaban:
Seperti semua yang ada di bawah spanduk "Agile", TDD adalah sesuatu yang terdengar bagus secara teori, tetapi dalam praktiknya tidak begitu jelas seberapa bagusnya (dan juga seperti kebanyakan hal "Agile", Anda diberitahu bahwa jika Anda tidak seperti itu, kamu salah melakukannya).
Definisi TDD tidak terukir di batu: orang-orang seperti Kent Beck menuntut tes non-kompilasi harus ditulis sebelum satu baris kode dan setiap baris kode harus ditulis untuk lulus tes gagal. Desain depan minimal dan semuanya didorongoleh tes. Itu tidak bekerja. Saya telah melihat aplikasi perusahaan besar yang dikembangkan menggunakan metodologi itu dan saya berharap itu adalah kode terburuk yang saya lihat dalam karir saya (tidak akan jauh; dan itu meskipun ada beberapa pengembang berbakat yang mengerjakannya). Dari apa yang saya lihat itu menghasilkan sejumlah besar tes dipikirkan dengan buruk yang terutama memvalidasi bahwa panggilan fungsi terjadi, bahwa pengecualian dilemparkan ketika variabel nol dan kerangka kerja mengejek mendapat latihan menyeluruh (whoop-de-whoop); kode produksi Anda akan sangat digabungkan ke tes ini dan mimpi refactoring yang konstan dan mudah tidak muncul - pada kenyataannya orang bahkan cenderung memperbaiki kode buruk karena semua tes itu akan rusak.
Sebaliknya saya pernah mendengar orang berpendapat bahwa TDD berarti merancang tes di muka pada tingkat tinggi sebagai bagian dari tahap perencanaan - di samping desain arsitektur. Tes ini dapat berubah selama pengembangan karena lebih banyak informasi tersedia, tetapi mereka telah dipertimbangkan dengan hati-hati dan menawarkan panduan yang baik tentang apa yang sebenarnya harus dilakukan kode. Bagi saya itu masuk akal.
sumber
Wawancara ( penulis Clojure ) Rich Hickey ini berisi yang berikut ini. Saya merasa 100% simpatik:
Pernyataan serupa lainnya dari wawancara buku Donald Knuth in Coders at Work , disalin dari sini :
sumber
Pengalaman negatif saya dengan TDD adalah pengalaman pertama saya. TDD terdengar hebat bagi saya, saya telah melakukan QA selama bertahun-tahun dan masih memiliki kengerian yang segar di pikiran saya. Saya ingin menghancurkan setiap bug sebelum membuatnya menjadi build. Sayangnya, menggunakan TDD tidak menjamin bahwa Anda akan menulis tes yang bagus. Bahkan, kecenderungan awal saya adalah menulis tes sederhana yang menghasilkan kode sederhana. Benar-benar kode sederhana yang berisi beberapa abstraksi. Tes sangat sederhana yang terjalin dengan internal kelas. Dan sekali Anda memiliki beberapa ribu tes bty itty di tempat Anda yakin tidak merasa seperti Anda bergerak lebih cepat ketika Anda harus mengubah seratus dari mereka untuk memperbaiki kode Anda untuk menggunakan konsep domain X yang sangat penting.
Lampu menyala bagi saya - TDD bukan keterampilan pengujian. Ini keterampilan desain. Ini hanya dapat mengarahkan Anda ke kode yang baik, sederhana, dapat diterapkan dengan praktik dan kesadaran konstan terhadap arah desain yang mengarahkan Anda. Jika Anda menulis tes demi cakupan kode, Anda akan membuat tes rapuh. Jika Anda menulis tes untuk membantu Anda mendesain abstraksi Anda, maka itu hanya cara yang lebih keras untuk menulis kode top-down. Anda dapat melihat kode dari perspektif penelepon terlebih dahulu, yang mendorong Anda untuk membuat hidupnya lebih mudah, daripada mencerminkan internal kelas ke tepi luarnya.
Saya pikir TDD berguna, tetapi saya tidak dogmatis tentang hal itu. Jika "tes tidak-bernilai" itu menyulitkan pemeliharaan - Hapus saja! Saya memperlakukan tes dengan cara yang sama seperti sisa kode. Jika itu bisa dihidupkan kembali dan menjadikannya lebih sederhana, maka lakukanlah!
Saya belum melihatnya secara pribadi, tetapi saya pernah mendengar bahwa beberapa tempat melacak cakupan kode dan jumlah pengujian. Jadi jika pengumpulan metrik adalah efek samping dari TDD, maka saya bisa melihatnya sebagai negatif juga. Saya akan dengan antusias menghapus 1000 baris kode, dan jika itu membatalkan 20 tes dan menurunkan% cakupan kode saya, oh well.
sumber
Saya akan pergi mengambil risiko di sini dan menyatakan dengan kejujuran brutal bahwa itu benar - benar buang-buang waktu ritualistik. (Dalam sebagian besar situasi.)
Saya membeli buku tentang Unit Testing yang juga membahas TDD, dan sementara saya setuju dengan manfaat UT, setelah sekitar seratus jam mencoba TDD, saya menyerah karenanya karena berbagai alasan. Saya agak mem-posting di sini, tetapi TDD:
Kekhawatiran lain adalah tingkat kesempurnaan yang diperdebatkan dimana seseorang harus melakukan TDD untuk melakukannya dengan sukses. Beberapa bersikeras bahwa jika TDD tidak dilakukan terus-menerus oleh semua orang di tim sejak awal proyek, Anda hanya akan menderita. Yang lain bersikeras bahwa tidak ada yang pernah melakukan TDD oleh buku. Jika keduanya benar, maka praktisi TDD menderita, apakah mereka menyadarinya atau tidak.
Tentu saja, jika diperdebatkan bahwa dengan melakukan hal-hal seperti TDD Anda akan sampai pada desain yang dapat bekerja dengan mudah dengan TDD, well, ada banyak cara yang lebih cepat untuk mencapai itu - yaitu, dengan benar-benar mempelajari konsep-konsep kompabilitas. Ada banyak sumber daya di luar sana, bahkan banyak teori matematika yang ketat (sebagian besar dalam pemrograman fungsional tetapi juga di bidang lain). Mengapa tidak menghabiskan semua waktu TDD Anda untuk belajar ?
Secara budaya, TDD menunjukkan gejala menjadi praktik ritualistik. Ia merasa bersalah; itu mendorong prosedur lebih dari pemahaman; memiliki banyak doktrin dan slogan ("berpura-puralah sampai Anda membuatnya" benar-benar cukup mengkhawatirkan jika Anda melihatnya secara objektif). Definisi Wikipedia tentang kata "ritual" sebenarnya cukup tepat:
sumber
Untuk menambahkan, masalah lain dengan TDD yang saya perhatikan adalah:
TDD menyebabkan perubahan yang tidak disengaja dalam fokus tim pengembangan dari Kode Kualitas ke Testcases dan Cakupan Kode! Saya pribadi tidak suka TDD karena membuat saya kurang kreatif dan membuat pengembangan perangkat lunak proses mekanik yang membosankan ! Unit testcases berguna ketika digunakan secara bijaksana tetapi menjadi beban ketika diperlakukan tujuan pengembangan perangkat lunak.
Saya kenal seorang pria yang seorang manajer dan secara teknis membosankan sekali terobsesi dengan TDD. Itu adalah hal yang sangat ajaib baginya sehingga dia percaya akan membawa solusi ajaib untuk semua masalah dalam perangkat lunaknya yang buruk arsitekturnya dengan kode yang paling tidak bisa dirawat. Belum lagi apa yang terjadi pada proyek itu - gagal total di tangannya, sementara semua testcenya berwarna hijau. Saya kira TDD membantunya mendapatkan semacam informasi statistik seperti "99/100 kasus saya berwarna hijau" dll dan itulah alasan obsesinya karena ia tidak akan pernah dapat mengevaluasi kualitas atau menyarankan peningkatan dalam desain.
sumber
Pengalaman negatif utama saya adalah mencoba menggunakan TDD untuk mengedit kode programmer lain yang tidak memiliki tes, atau tes integrasi yang sangat, sangat dasar. Ketika saya pergi untuk menambahkan fitur, atau memperbaiki masalah dengan kode tersebut; Saya lebih suka menulis tes pertama (cara TDD). Sayangnya, kodenya tergabung erat, dan saya tidak dapat menguji apa pun tanpa banyak refactoring.
Refactoring adalah latihan yang bagus, tetapi diperlukan untuk membuat kode menjadi kondisi yang dapat diuji. Dan setelah langkah ini, saya tidak memiliki checks and balances untuk melihat apakah perubahan saya merusak sesuatu; singkat menjalankan aplikasi dan memeriksa setiap kasus penggunaan.
Di sisi lain, menambahkan fitur / memperbaiki bug ke proyek TDD menjadi sangat mudah. Secara alami, kode yang ditulis dengan TDD biasanya cukup dipisahkan dengan potongan-potongan kecil untuk dikerjakan.
Bagaimanapun, TDD adalah pedoman. Ikuti sampai ke titik di mana Anda menemukan Anda mendapatkan efektivitas maksimum. Cakupan pengujian yang layak dan kode yang dipisahkan, kode yang ditulis dengan baik.
sumber
Saya membuat pengalaman yang kadang-kadang saya terlalu bergantung pada tes saya ketika datang ke desain sistem. Saya pada dasarnya terlalu rendah dalam detail implementasi seluk-beluk untuk mengambil langkah mundur untuk melihat gambar yang lebih besar. Ini sering menghasilkan desain yang rumit dan tidak perlu. Saya tahu, saya seharusnya memperbaiki kode tetapi kadang-kadang saya mendapat kesan bahwa saya bisa menghemat banyak waktu dengan mengambil langkah mundur lebih sering.
Yang sedang berkata, jika Anda memiliki kerangka kerja seperti rel di mana keputusan arsitektur Anda sangat terbatas masalah ini pada dasarnya tidak ada.
Masalah lain adalah ketika Anda memercayai tes Anda secara membabi buta. Kebenarannya adalah - seperti kode lainnya - tes Anda dapat memiliki bug juga. Jadi, sama pentingnya dengan tes Anda seperti Anda terhadap implementasi Anda.
sumber
Sebagai penggemar berat TDD saya terkadang melihat kekurangan ini
Biaya pemeliharaan kode uji untuk pengujian serupa, yang hanya sedikit berbeda (dibuat melalui duplikasi kode (alias copy-paste-inheritance)). Jika Anda sudah memilikinya, mudah untuk membuat yang serupa. Tetapi jika Anda tidak memperbaiki kode tes, dengan menghilangkan duplikasi kode menjadi metode pembantu, Anda mungkin perlu waktu untuk memperbaiki tes jika rincian implementasi kode bisnis Anda berubah.
Jika Anda berada di bawah tekanan waktu, Anda mungkin tergoda untuk menghilangkan tes yang rusak (atau berkomentar keluar) daripada memperbaikinya . Dengan cara ini Anda kehilangan investasi dalam tes
sumber
Saya belum menemukan lebih dari satu skenario sebagai pengembang game di mana TDD berharga. Dan contoh di mana itu, adalah sepotong kode yang murni bersifat matematika dan membutuhkan pendekatan yang kuat untuk menguji sejumlah besar kasus tepi secara bersamaan - suatu kebutuhan yang langka.
Mungkin sesuatu, suatu hari nanti akan berubah pikiran, tetapi di antara praktik XP, ide refactoring tanpa ampun , dan kode yang berkembang bentuknya sendiri jauh lebih penting dan mengarah pada produktivitas terbesar bagi saya, lih. kutipan dari makalah oleh James Newkirk :
Konsep keberanian dan pengetatan putaran umpan balik yang dia sebutkan juga, menurut saya, adalah kunci produktivitas.
sumber
Pengalaman TDD negatif saya, sebatas mungkin, hanya mengetahui dari mana harus memulai! Sebagai contoh, saya akan mencoba untuk melakukan sesuatu TDD dan entah tidak tahu di mana harus mulai melarang pengujian hal-hal sepele (bisakah saya membuat
Foo
objek baru, dapatkah saya meneruskanQuux
keBaz
, dan sejenisnya. Tes yang tidak menguji apa pun ), atau jika saya mencoba mengimplementasikannya dalam proyek yang ada maka saya menemukan bahwa saya harus menulis ulang berbagai kelas untuk dapat menggunakannya dalam TDD. Hasil akhirnya adalah bahwa saya dengan cepat meninggalkan gagasan itu sepenuhnya.Mungkin tidak membantu yang sering saya satu-satunya orang di seluruh perusahaan yang tahu apa pengujian unit (TDD atau sebaliknya) dan mengapa itu hal yang baik.
sumber
Foo
dengan benda-benda tiruan daripadaQuux
danBaz
langsung, maka Anda dapat memanggil fungsi yang ingin Anda uji dan kemudian memeriksa bahwa tiruan itu dipanggil dengan fungsi yang Anda harapkan. Objek tiruan adalah teknologi yang memungkinkan yang membantu memisahkan unit dan membuatnya unit dapat diuji. Inilah sebabnya mengapa lajang jahat, karena Anda sering tidak bisa begitu saja mengejek mereka. * 8 ')Fanatik TDD.
Bagi saya, mereka hanyalah satu dari sekian banyak orang gila agama yang mengetuk pintu saya, mencoba membuktikan bahwa cara saya dalam melakukan berbagai hal tidak dapat diperbaiki dan satu-satunya jalan menuju keselamatan adalah Yesus, Kent Back, atau Unit Testing.
IMO, kebohongan terbesar mereka adalah bahwa TDD akan menuntun Anda untuk
menyelamatkandesain algoritma yang lebih baik. Lihat pemecah Soduku terkenal yang ditulis dalam TDD: di sini , di sini , di sini , di sini dan di siniDan membandingkannya, pemecah sudoku Peter Norvig dilakukan bukan dengan menggunakan TDD, tetapi menggunakan teknik kuno: http://norvig.com/sudoku.html
sumber
Jika Anda menggunakan TDD dari artikel "fanatik" ini, Anda akan merasa tidak aman karena merasa perangkat lunak Anda tidak memiliki kesalahan.
sumber
TDD memiliki beberapa manfaat:
TDD adalah tentang investasi jangka panjang. Upaya ini terbayar ketika Anda mencapai mode pemeliharaan aplikasi Anda, dan jika aplikasi tidak direncanakan untuk mencapai titik itu, Anda mungkin tidak pernah memulihkan investasi.
Saya menganggap siklus merah-hijau TDD dengan langkah-langkah bayi mirip dengan daftar periksa untuk pesawat. Sangat menjengkelkan dan melelahkan untuk memeriksa setiap hal di dalam pesawat sebelum lepas landas terutama jika itu sederhana (langkah-langkah TDD bayi), tetapi telah ditemukan bahwa hal itu meningkatkan keselamatan. Selain memverifikasi semuanya berfungsi, itu pada dasarnya mengatur ulang pesawat . Dengan kata lain, sebuah pesawat dinyalakan ulang sebelum setiap take-off.
sumber
Pengalaman negatif saya tentang TDD adalah sesuatu yang saya rasakan dengan banyak hal baru dan hyped. Sebenarnya saya menikmati TDD karena memastikan validitas kode saya, dan bahkan lebih penting: saya dapat mengenali tes yang gagal, setelah menambahkan kode baru atau segala jenis refactoring.
Yang mengganggu saya tentang TDD adalah kenyataan bahwa ada banyak aturan atau pedoman tentang hal itu. Karena ini masih sangat baru, kami sebagian besar dari kita mengalami untuk menjadi pemula di TDD. Jadi apa yang berhasil untuk sebagian dari kita, mungkin tidak bekerja untuk yang lain. Yang ingin saya katakan adalah, bahwa tidak ada cara nyata "salah atau benar" untuk melakukan TDD: Ada cara yang bekerja untuk saya - dan tim saya jika saya memilikinya.
Jadi selama Anda menulis tes - sebelum atau setelah kode produksi tidak terlalu penting IMHO - saya tidak yakin apakah tes didorong benar-benar berarti Anda harus mengikuti semua pedoman yang dinyatakan sekarang, karena mereka belum terbukti menjadi solusi ideal untuk pekerjaan sehari-hari. Jika Anda menemukan cara yang lebih baik dalam menulis tes, Anda harus mempostingnya di blog, bahas di sini, atau tulis artikel tentang itu. Jadi dalam sepuluh tahun atau lebih kita mungkin telah berbagi pengalaman yang cukup untuk dapat mengetahui aturan TDD mana yang dapat dianggap baik atau tidak dalam situasi tertentu.
sumber
Saya telah, pada lebih dari satu kesempatan, menulis kode yang saya buang pada hari berikutnya karena canggung. Saya memulai kembali dengan TDD dan solusinya lebih baik. Jadi saya belum punya terlalu banyak pengalaman TDD negatif. Namun demikian, saya telah menghabiskan waktu untuk memikirkan masalah dan mencari solusi yang lebih baik di luar ruang TDD.
sumber
Saya telah menemukan TDD berkinerja buruk ketika datang ke sistem yang muncul. Saya adalah pengembang permainan video, dan baru-baru ini menggunakan TDD untuk membuat sistem yang menggunakan beberapa perilaku sederhana untuk membuat gerakan yang tampak realistis untuk suatu entitas.
Misalnya, ada perilaku yang bertanggung jawab untuk memindahkan Anda dari area berbahaya dari berbagai jenis, dan yang bertanggung jawab untuk memindahkan Anda ke area menarik dari berbagai jenis. Dengan menggabungkan output dari masing-masing perilaku menciptakan gerakan akhir.
Nyali sistem diimplementasikan dengan mudah, dan TDD berguna di sini untuk menentukan apa yang harus bertanggung jawab atas setiap subsistem.
Namun saya mengalami masalah ketika menentukan bagaimana perilaku berinteraksi, dan yang lebih penting bagaimana mereka berinteraksi dari waktu ke waktu. Seringkali tidak ada jawaban yang benar, dan meskipun tes awal saya lulus, QA dapat terus menemukan kasus tepi di mana sistem tidak berfungsi. Untuk menemukan solusi yang benar, saya harus mengulangi beberapa perilaku yang berbeda, dan jika saya memperbarui tes setiap kali untuk mencerminkan perilaku baru sebelum saya memeriksa mereka bekerja dalam permainan, saya mungkin akhirnya membuang tes berulang kali. Jadi saya menghapus tes-tes itu.
Saya seharusnya memiliki tes yang lebih kuat yang menangkap kasus-kasus tepi yang ditemukan QA, tetapi ketika Anda memiliki sistem seperti ini yang berada di atas banyak sistem fisika dan gameplay, dan Anda berurusan dengan perilaku dari waktu ke waktu, itu menjadi sedikit mimpi buruk untuk menentukan dengan tepat apa yang terjadi.
Saya hampir pasti membuat kesalahan dalam pendekatan saya, dan seperti saya katakan untuk nyali sistem TDD bekerja dengan cemerlang, dan bahkan mendukung beberapa refaktor yang optimal.
sumber