Dalam proyek saya saat ini (sebuah game, dalam C ++), saya memutuskan untuk menggunakan Test Driven Development 100% selama pengembangan.
Dalam hal kualitas kode, ini sangat bagus. Kode saya tidak pernah dirancang dengan begitu baik atau tanpa bug. Saya tidak merasa ngeri ketika melihat kode yang saya tulis setahun yang lalu pada awal proyek, dan saya telah mendapatkan pengertian yang jauh lebih baik tentang bagaimana menyusun berbagai hal, tidak hanya agar lebih mudah diuji, tetapi lebih mudah untuk diterapkan dan digunakan .
Namun ... sudah setahun sejak saya memulai proyek. Memang, saya hanya bisa mengerjakannya di waktu luang saya, tetapi TDD masih memperlambat saya jauh dibandingkan dengan apa yang saya terbiasa. Saya membaca bahwa kecepatan pengembangan yang lebih lambat menjadi lebih baik dari waktu ke waktu, dan saya benar-benar memikirkan tes jauh lebih mudah daripada sebelumnya, tapi saya sudah melakukannya selama satu tahun sekarang dan saya masih bekerja dengan kecepatan siput.
Setiap kali saya memikirkan langkah selanjutnya yang perlu dikerjakan, saya harus berhenti setiap waktu dan berpikir tentang bagaimana saya akan menulis tes untuk itu, untuk memungkinkan saya menulis kode yang sebenarnya. Terkadang saya macet selama berjam-jam, tahu persis kode apa yang ingin saya tulis, tetapi tidak tahu cara memecahnya cukup halus untuk sepenuhnya menutupinya dengan tes. Di lain waktu, saya akan dengan cepat memikirkan selusin tes, dan menghabiskan satu jam menulis tes untuk menutupi sepotong kecil kode nyata yang seharusnya memerlukan waktu beberapa menit untuk menulis.
Atau, setelah menyelesaikan tes ke-50 untuk mencakup entitas tertentu dalam permainan dan semua aspek pembuatan dan penggunaannya, saya melihat daftar tugas yang harus saya lakukan dan melihat entitas berikutnya yang akan dikodekan, dan ngeri ngeri membayangkan menulis 50 tes serupa lainnya untuk mengimplementasikannya.
Sudah sampai pada titik itu, melihat kemajuan tahun lalu, saya sedang mempertimbangkan meninggalkan TDD demi "menyelesaikan proyek sialan". Namun, menyerahkan kualitas kode yang menyertainya bukanlah sesuatu yang saya harapkan. Saya takut jika saya berhenti menulis tes, maka saya akan keluar dari kebiasaan membuat kode jadi modular dan dapat diuji.
Apakah saya mungkin melakukan sesuatu yang salah untuk tetap lambat dalam hal ini? Adakah alternatif yang mempercepat produktivitas tanpa sepenuhnya kehilangan manfaat? TAD? Kurang cakupan tes? Bagaimana orang lain dapat bertahan hidup tanpa TDD tanpa membunuh semua produktivitas dan motivasi?
sumber
Jawaban:
Mari saya mulai dengan berterima kasih kepada Anda untuk berbagi pengalaman Anda dan menyuarakan keprihatinan Anda ... yang harus saya katakan tidak biasa.
Dan itu membawa saya ke pertanyaan terakhir: Bagaimana saya menjadi lebih baik? Jawaban saya (atau An) adalah Baca, Renungkan, dan Berlatih.
misalnya Akhir-akhir ini, saya tetap mengawasi
sumber
Anda tidak perlu cakupan tes 100% persen. Bersikap pragmatis.
sumber
a = x + y
dan meskipun semua baris dalam kode dieksekusi dalam tes, tes hanya diuji untuk kasus di mana y = 0, sehingga bug (seharusnyaa = x - y
) tidak pernah ditemukan dalam tes.Itu sebenarnya salah.
Tanpa TDD, Anda menghabiskan beberapa minggu menulis kode yang sebagian besar bekerja dan menghabiskan tahun berikutnya "pengujian" dan memperbaiki banyak (tetapi tidak semua) bug.
Dengan TDD, Anda menghabiskan satu tahun menulis kode yang benar-benar berfungsi. Kemudian Anda melakukan pengujian integrasi akhir selama beberapa minggu.
Waktu yang berlalu mungkin akan sama. Perangkat lunak TDD akan jauh lebih berkualitas.
sumber
Ini membuat saya bertanya-tanya berapa banyak Anda mengikuti langkah "Refactor" dari TDD.
Ketika semua tes Anda lulus, ini saatnya bagi Anda untuk memperbaiki kode dan menghapus duplikasi. Sementara orang biasanya mengingat ini, kadang-kadang mereka lupa bahwa ini juga saatnya untuk memperbaiki tes mereka juga, untuk menghapus duplikasi dan menyederhanakan hal-hal.
Jika Anda memiliki dua entitas yang bergabung menjadi satu untuk memungkinkan kode digunakan kembali, pertimbangkan juga untuk menggabungkan pengujian mereka. Anda benar-benar hanya perlu menguji perbedaan inkremental dalam kode Anda. Jika Anda tidak secara teratur melakukan perawatan pada tes Anda, mereka dapat dengan cepat menjadi berat.
Beberapa poin filosofis tentang TDD yang mungkin bermanfaat:
EDIT: Pada topik filsafat unit testing, saya pikir ini mungkin menarik untuk Anda baca: The Way of Testivus
Dan poin yang lebih praktis, jika tidak selalu sangat membantu:
sumber
Pertanyaan yang sangat menarik.
Yang penting untuk dicatat, adalah bahwa C ++ tidak mudah diuji, dan game, secara umum, juga merupakan kandidat yang sangat buruk untuk TDD. Anda tidak dapat menguji apakah OpenGL / DirectX menggambar segitiga merah dengan driver X, dan kuning dengan driver Y dengan mudah. Jika bump map, vektor normal tidak terbalik setelah shader berubah. Anda juga tidak dapat menguji kliping masalah pada versi driver dengan tindakan berbeda, dan sebagainya. Perilaku menggambar yang tidak terdefinisi karena panggilan yang salah juga dapat diuji hanya dengan peninjauan kode yang akurat dan SDK. Suara juga merupakan kandidat yang buruk. Multithreading, yang sekali lagi cukup penting untuk gim, cukup berguna untuk unit-test. Jadi itu sulit.
Pada dasarnya gaming banyak GUI, suara dan utas. GUI, bahkan dengan komponen standar yang dapat Anda kirim WM_, sulit untuk unit-test.
Jadi yang dapat Anda uji, adalah kelas pemuatan model, kelas pemuatan tekstur, pustaka matriks dan semacamnya, yang tidak banyak kode, dan, cukup sering, tidak dapat digunakan kembali, jika itu hanya proyek pertama Anda. Juga, mereka dikemas ke dalam format berpemilik, jadi kemungkinan besar input pihak ketiga tidak akan banyak berbeda, kecuali jika Anda merilis alat modding dll.
Kemudian lagi, saya bukan guru atau penginjil TDD, jadi ambil semua itu dengan sebutir garam.
Saya mungkin akan menulis beberapa tes untuk komponen inti utama (misalnya perpustakaan matriks, perpustakaan gambar). Tambahkan sekelompok
abort()
input yang tidak terduga di setiap fungsi. Dan yang paling penting, berkonsentrasi pada kode yang tahan / tangguh yang tidak mudah rusak.Mengenai satu kesalahan, penggunaan pintar C ++, RAII dan desain yang bagus sangat membantu untuk mencegahnya.
Pada dasarnya Anda harus melakukan banyak hal hanya untuk menutupi dasar-dasarnya jika Anda ingin merilis game. Saya tidak yakin apakah TDD akan membantu.
sumber
Saya setuju dengan jawaban lain, tetapi saya juga ingin menambahkan poin yang sangat penting: Biaya refactoring !!
Dengan tes unit yang ditulis dengan baik, Anda dapat dengan aman melakukan penulisan ulang kode Anda. Pertama, unit test yang ditulis dengan baik memberikan dokumentasi yang sangat baik tentang maksud kode Anda. Kedua, efek samping yang tidak menguntungkan dari refactoring Anda akan ditangkap di ruang tes yang ada. Dengan demikian, Anda telah menjamin bahwa asumsi kode lama Anda juga berlaku untuk kode baru Anda.
sumber
Ini sama sekali berbeda dari pengalaman saya. Anda cerdas luar biasa dan menulis kode tanpa bug, (mis. Dinonaktifkan karena satu kesalahan) atau Anda tidak menyadari kode Anda memiliki bug yang mencegah program Anda bekerja, sehingga tidak benar-benar selesai.
TDD adalah tentang memiliki kerendahan hati untuk mengetahui bahwa Anda (dan saya!) Membuat kesalahan.
Bagi saya waktu menulis unittests lebih dari yang disimpan dalam mengurangi waktu debug untuk proyek yang dilakukan menggunakan TDD dari awal.
Jika Anda tidak membuat kesalahan maka mungkin TDD tidak sepenting bagi Anda seperti bagi saya!
sumber
Saya hanya punya beberapa komentar:
Sepertinya Anda mencoba menguji semuanya . Anda mungkin tidak seharusnya, hanya kasus-kasus berisiko tinggi dan tepi sepotong kode / metode tertentu. Saya cukup yakin aturan 80/20 berlaku di sini: Anda menghabiskan 80% menulis tes untuk 20% terakhir dari kode Anda atau kasus yang tidak tercakup.
Memprioritaskan. Masuk ke pengembangan perangkat lunak tangkas, dan buat daftar apa yang benar-benar benar-benar perlu Anda lakukan untuk rilis dalam waktu satu bulan. Lalu lepaskan, begitu saja. Ini akan membuat Anda berpikir tentang prioritas fitur. Ya, itu akan keren jika karakter Anda bisa melakukan backflip, tetapi apakah itu memiliki nilai bisnis ?
TDD baik, tetapi hanya jika Anda tidak bertujuan untuk cakupan uji 100%, dan itu tidak jika hal itu membuat Anda tidak menghasilkan nilai bisnis yang sebenarnya (yaitu fitur, hal-hal yang menambah sesuatu ke permainan Anda).
sumber
Ya, menulis tes dan kode mungkin memakan waktu lebih lama dari sekadar menulis kode - tetapi menulis kode dan pengujian unit terkait (menggunakan TDD) jauh lebih mudah diprediksi daripada menulis kode dan kemudian men-debug-nya.
Debugging hampir dihilangkan ketika menggunakan TDD - yang membuat semua proses pengembangan jauh lebih mudah diprediksi dan pada akhirnya - bisa dibilang lebih cepat.
Refactoring yang konstan - tidak mungkin untuk melakukan refactoring yang serius tanpa unit test suite yang komprehensif. Cara paling efisien untuk membangun jaring pengaman berbasis pengujian unit adalah selama TDD. Kode yang dire-refursi secara signifikan meningkatkan produktivitas keseluruhan dari desainer / tim yang mengelola kode.
sumber
Pertimbangkan untuk mempersempit ruang lingkup gim Anda dan dapatkan di mana seseorang dapat memainkannya atau Anda melepaskannya. Pertahankan standar pengujian Anda tanpa harus menunggu terlalu lama untuk merilis game Anda mungkin merupakan jalan tengah untuk membuat Anda tetap termotivasi. Umpan balik dari pengguna Anda dapat memberikan manfaat dalam jangka panjang dan pengujian Anda membuat Anda merasa nyaman dengan penambahan dan perubahan.
sumber