Dalam teks tentang TDD saya sering membaca tentang "menghapus duplikasi" atau "meningkatkan keterbacaan" selama langkah refactoring. Tapi apa yang membuat saya menghapus fungsi yang tidak digunakan?
Sebagai contoh katakanlah ada kelas C
dengan metode a()
dan b()
. Sekarang saya pikir akan menyenangkan untuk memiliki metode f()
yang didorong ke dalamnya C
. Bahkan f()
menggantikan semua panggilan b()
dengan pengecualian unit test yang didefinisikan / dijelaskan b()
. Tidak diperlukan lagi - kecuali untuk tes.
Apakah hanya menyimpan untuk menghapus b()
dan semua tes yang menggunakannya? Apakah itu bagian dari "meningkatkan keterbacaan"?
unit-testing
refactoring
tdd
readability
TobiMcNamobi
sumber
sumber
Jawaban:
Ya tentu saja. Kode yang paling mudah dibaca adalah yang tidak ada.
Yang mengatakan, refactoring umumnya berarti memperbaiki kode tanpa mengubah perilakunya. Jika Anda memikirkan sesuatu yang meningkatkan kode, lakukan saja. Anda tidak perlu memasukkannya ke dalam lubang merpati sebelum Anda diizinkan melakukannya.
sumber
Menghapus metode publik bukan "refactoring" - refactoring mengubah implementasi sambil terus melewati tes yang ada.
Namun, menghapus metode yang tidak dibutuhkan adalah perubahan desain yang masuk akal.
TDD menarik ini sampai batas tertentu, karena dalam meninjau tes, Anda dapat mengamati bahwa itu menguji metode yang tidak dibutuhkan. Tes mendorong desain Anda, karena Anda dapat pergi "Lihat, tes ini tidak ada hubungannya dengan tujuan saya".
Ini mungkin mengungkapkan dirinya lebih pada tingkat pengujian yang lebih tinggi, dalam hubungannya dengan alat cakupan kode. Jika Anda menjalankan tes integrasi dengan cakupan kode, dan melihat bahwa metode tidak dipanggil, itu adalah petunjuk bahwa metode tidak digunakan. Analisis kode statis juga dapat menunjukkan bahwa metode tidak digunakan.
Ada dua pendekatan untuk menghapus suatu metode; keduanya bekerja dalam keadaan yang berbeda:
Hapus metode. Ikuti kesalahan kompilasi, untuk menghapus kode dan tes yang bergantung. Jika Anda puas bahwa tes yang terpengaruh dapat dibuang, lakukan perubahan Anda. Jika tidak, putar kembali.
Hapus tes yang Anda rasa sudah usang. Jalankan seluruh rangkaian uji Anda dengan cakupan kode. Hapus metode yang belum dilakukan oleh test suite.
(Ini mengandaikan bahwa ruang tes Anda memiliki cakupan yang baik untuk memulai).
sumber
IMHO, siklus TDD khas akan terlihat seperti ini:
tulis gagal tes untuk f () (mungkin berdasarkan tes untuk b ()): tes menjadi merah
implementasikan uji f () -> menjadi hijau
refactor : -> hapus b () dan semua tes untuk b ()
Untuk langkah terakhir, Anda dapat mempertimbangkan untuk menghapus b () terlebih dahulu dan melihat apa yang terjadi (ketika menggunakan bahasa yang dikompilasi, kompiler hanya akan mengeluh tentang tes yang ada, ketika tidak, tes unit lama untuk b akan gagal, jadi itu adalah jelas Anda harus menghapusnya juga).
sumber
Ya itu.
Kode terbaik, paling bebas bug, dan paling mudah dibaca adalah kode yang tidak ada. Berusaha keras untuk menulis sebanyak mungkin non-kode sambil memenuhi persyaratan Anda.
sumber
Ini diinginkan untuk dihapus
b()
setelah tidak lagi digunakan, karena alasan yang sama diinginkan untuk tidak menambahkan fungsi yang tidak digunakan di tempat pertama. Apakah Anda menyebutnya "keterbacaan" atau sesuatu yang lain, semua yang dianggap sama itu merupakan peningkatan pada kode yang tidak mengandung apa pun yang tidak ada gunanya. Demi memiliki setidaknya satu ukuran spesifik yang lebih baik tidak memilikinya, menghapusnya menjamin bahwa biaya pemeliharaan di masa depan setelah perubahan itu nol!Saya belum menemukan teknik khusus yang diperlukan untuk benar-benar menghapusnya dengan tes, karena ada pemikiran untuk mengganti
b()
dengan sesuatu yang baru tentu saja harus disertai dengan pertimbangan semua kode yang sedang dipanggilb()
, dan tes adalah bagian dari "semua kode ".Garis penalaran yang umumnya bekerja untuk saya adalah bahwa pada titik di mana saya perhatikan yang
f()
telah menjadib()
usang, karena itub()
harus paling tidak usang, dan saya mencari untuk menemukan semua panggilanb()
dengan maksud untuk menggantikannya dengan panggilan kef()
, saya pertimbangkan juga kode tes . Secara khusus, jikab()
tidak lagi diperlukan maka saya bisa dan harus menghapus tes unitnya.Anda benar bahwa tidak ada yang memaksa saya untuk memperhatikan bahwa
b()
tidak lagi diperlukan. Itu masalah keterampilan (dan, seperti kata ramping, laporan cakupan kode pada tes tingkat yang lebih tinggi). Jika hanya tes unit, dan tidak ada tes fungsional, lihatb()
, maka saya bisa optimis dengan hati-hati bahwa itu bukan bagian dari antarmuka yang diterbitkan dan oleh karena itu menghapus itu bukan perubahan yang melanggar untuk kode apa pun yang tidak di bawah kendali langsung saya.Siklus merah / hijau / refactor tidak secara eksplisit menyebutkan tes pelepasan. Selanjutnya, menghapus
b()
melanggar terbuka / tertutup prinsip karena jelas komponen Anda adalah terbuka untuk modifikasi. Jadi jika Anda ingin menganggap langkah ini sebagai sesuatu di luar TDD sederhana, silakan. Misalnya, Anda mungkin memiliki beberapa proses untuk mendeklarasikan tes "buruk", yang dapat diterapkan dalam kasus ini untuk menghapus tes dengan alasan tes untuk sesuatu yang seharusnya tidak ada di sana (fungsi yang tidak perlu)b()
).Saya pikir dalam praktiknya kebanyakan orang mungkin mengizinkan sejumlah desain ulang untuk dilakukan bersamaan dengan siklus merah / hijau / refactor, atau mereka menganggap menghapus tes unit redundan sebagai bagian valid dari "refactor" meskipun secara tegas berbicara itu bukan refactoring. Tim Anda dapat memutuskan berapa banyak drama dan dokumen yang harus dilibatkan dalam membenarkan keputusan ini.
Lagi pula, jika
b()
itu penting maka akan ada tes fungsional untuk itu, dan itu tidak akan dihapus ringan, tetapi Anda sudah mengatakan bahwa hanya ada tes unit. Jika Anda tidak benar membedakan antara tes unit (ditulis dengan desain internal kode saat ini, yang telah Anda ubah) dan tes fungsional (ditulis ke antarmuka yang diterbitkan, yang mungkin Anda tidak ingin ubah) maka Anda harus lebih berhati-hati tentang menghapus unit test.sumber
Satu hal yang harus selalu diingat adalah bahwa kita sekarang menggunakan REPOSITORI KODE dengan VERSION CONTROL. Kode yang dihapus itu tidak benar-benar hilang ... masih ada di suatu tempat di iterasi sebelumnya. Jadi hancurkan! Jadilah liberal dengan kunci hapus, karena Anda selalu dapat kembali dan mengambil metode elegan yang berharga yang Anda pikir mungkin berguna suatu hari nanti ... jika suatu hari nanti pernah datang. Itu disana.
Tentu saja, itu sejalan dengan peringatan dari penyakit dan bahaya rilis yang tidak kompatibel dengan belakang ... aplikasi eksternal yang bergantung pada implementasi antarmuka Anda, yang sekarang menjadi yatim piatu dengan kode Anda yang tiba-tiba (usang).
sumber