Saat berdiskusi, salah satu kolega saya mengatakan bahwa ia mengalami beberapa kesulitan dengan proyeknya saat ini ketika mencoba menyelesaikan bug. "Ketika saya memecahkan satu bug, sesuatu yang lain berhenti bekerja di tempat lain", katanya.
Saya mulai berpikir tentang bagaimana ini bisa terjadi, tetapi tidak bisa mengetahuinya.
- Saya kadang-kadang memiliki masalah yang sama ketika saya terlalu lelah / mengantuk untuk melakukan pekerjaan dengan benar dan memiliki pandangan keseluruhan dari bagian kode yang saya kerjakan. Di sini, masalahnya tampaknya selama beberapa hari atau minggu, dan tidak terkait dengan fokus kolega saya.
- Saya juga bisa membayangkan masalah ini muncul pada proyek yang sangat besar, dikelola dengan sangat buruk , di mana rekan satu tim tidak tahu siapa yang melakukan apa, dan apa efek pada pekerjaan orang lain dapat memiliki perubahan yang mereka lakukan. Ini bukan masalahnya di sini juga: itu adalah proyek yang agak kecil dengan hanya satu pengembang.
- Ini juga bisa menjadi masalah dengan basis kode lama, tidak terpelihara, dan tidak pernah didokumentasikan , di mana satu-satunya pengembang yang benar-benar dapat membayangkan konsekuensi dari perubahan telah meninggalkan perusahaan bertahun-tahun yang lalu. Di sini, proyek baru saja dimulai, dan pengembang tidak menggunakan basis kode siapa pun.
Jadi apa yang bisa menjadi penyebab masalah tersebut pada basis kode berukuran kecil dan segar yang ditulis oleh pengembang tunggal yang tetap fokus pada pekerjaannya ?
Apa yang bisa membantu?
- Tes unit (tidak ada)?
- Arsitektur yang tepat (saya cukup yakin bahwa basis kode tidak memiliki arsitektur sama sekali dan ditulis tanpa pemikiran awal), memerlukan seluruh refactoring?
- Pemrograman pasangan?
- Sesuatu yang lain
project-management
refactoring
Arseni Mourzenko
sumber
sumber
Jawaban:
Itu tidak ada hubungannya dengan fokus, ukuran proyek, dokumentasi, atau masalah proses lainnya. Masalah seperti itu biasanya merupakan hasil dari pemasangan yang berlebihan dalam desain, yang membuatnya sangat sulit untuk mengisolasi perubahan.
sumber
Salah satu penyebabnya adalah hubungan yang erat antara komponen-komponen perangkat lunak Anda: jika tidak ada antarmuka antar komponen yang sederhana dan terdefinisi dengan baik, maka bahkan perubahan kecil dalam satu bagian kode dapat menimbulkan efek samping yang tidak diharapkan di bagian lain dari kode.
Sebagai contoh, belakangan ini saya sedang mengerjakan sebuah kelas yang mengimplementasikan komponen GUI dalam aplikasi saya. Selama berminggu-minggu bug baru dilaporkan, saya memperbaikinya, dan bug baru muncul di tempat lain. Saya menyadari bahwa kelas telah tumbuh terlalu besar, melakukan terlalu banyak hal, dan banyak metode bergantung pada metode lain yang dipanggil dalam urutan yang benar agar dapat bekerja dengan baik.
Alih-alih memperbaiki tiga bug terbaru, saya melakukan beberapa refactoring yang kuat: membagi komponen menjadi kelas utama ditambah kelas MVC (tiga kelas tambahan). Dengan cara ini saya harus membagi kode menjadi lebih kecil, potongan-potongan sederhana dan mendefinisikan antarmuka yang lebih jelas. Setelah refactoring semua bug dipecahkan dan tidak ada bug baru yang dilaporkan.
sumber
Mudah untuk satu bug untuk menutupi yang lain. Misalkan bug "A" menghasilkan fungsi yang salah dipanggil untuk menangani input. Ketika bug "A" diperbaiki, tiba-tiba fungsi yang benar dipanggil, yang belum pernah diuji.
sumber
Nah, penyebab langsungnya adalah dua kesalahan membuat yang benar, atau setidaknya membuat yang tidak-jelas-salah. Salah satu bagian kode mengkompensasi perilaku yang salah dari bagian lainnya. Atau jika bagian pertama tidak "salah" seperti itu, ada beberapa perjanjian tidak tertulis antara dua bagian yang dilanggar ketika kode diubah.
Misalnya, misalkan fungsi A dan B menggunakan konvensi berbasis nol untuk beberapa kuantitas, sehingga mereka bekerja bersama dengan benar, tetapi C menggunakan satu, Anda mungkin "memperbaiki" A untuk bekerja dengan C dan kemudian menemukan masalah dengan B.
Masalah yang lebih dalam adalah kurangnya verifikasi independen atas kebenaran masing-masing bagian. Tes unit dirancang untuk mengatasi ini. Mereka juga bertindak sebagai spesifikasi input yang tepat. Misalnya serangkaian tes yang baik akan memperjelas bahwa fungsi A dan B mengharapkan input berbasis 0 dan berbasis C1.
Mendapatkan spesifikasi yang benar juga dapat dilakukan dengan cara lain, dari dokumen resmi hingga komentar yang baik dalam kode, tergantung pada kebutuhan proyek. Kuncinya adalah memahami apa yang diharapkan setiap komponen dan apa yang dijanjikannya, sehingga Anda dapat menemukan inkonsistensi.
Arsitektur yang baik membantu masalah dalam memahami kode, membuatnya menjadi lebih mudah. Pemrograman pasangan sangat membantu untuk menghindari bug sejak awal, atau menemukannya lebih cepat.
Semoga ini membantu.
sumber
Kopling ketat, kurangnya pengujian, ini mungkin penyebab paling umum. Pada dasarnya masalah umum hanyalah standar dan prosedur yang jelek. Lain hanya mengelola kode yang salah untuk mendapatkan keberuntungan untuk sementara waktu dengan perilaku yang benar. Pertimbangkan
memcpy
bug dari Linus Torvalds di mana perubahan implementasinya mengekspos (tidak menyebabkan) bug pada klien yang digunakanmemcpy
di tempat-tempat di mana mereka seharusnya digunakanmemmove
dengan sumber dan tujuan yang tumpang tindih.sumber
Sepertinya bug "baru" ini sebenarnya bukan bug "baru". Mereka tidak masalah, sampai kode lain yang rusak, benar-benar diperbaiki. Dengan kata lain, kolega Anda tidak menyadari bahwa ia sebenarnya memiliki dua bug sepanjang waktu. Jika kode yang tidak terbukti rusak tidak rusak, itu tidak akan gagal, setelah bagian kode yang lain benar-benar diperbaiki.
Dalam kedua kasus, rejimen tes otomatis yang lebih baik mungkin bermanfaat. Sepertinya kolega Anda perlu menguji unit basis kode saat ini. Di masa depan pengujian regresi akan memverifikasi kode yang ada terus berfungsi.
sumber
Tingkatkan luas rejimen tes otomatis Anda. SELALU menjalankan uji penuh sebelum melakukan perubahan kode. Dengan begitu, Anda akan mendeteksi efek buruk perubahan Anda.
sumber
Saya baru saja mengalami ini ketika tes salah. Tes memeriksa status izin yang diberikan yang benar! Saya memperbarui kode dan menjalankan tes izin. Itu berhasil. Lalu saya menjalankan semua tes. Semua tes lain yang menggunakan sumber yang diperiksa gagal. Saya mengoreksi tes dan pemeriksaan izin, tetapi pada awalnya ada sedikit kepanikan.
Spesifikasi yang tidak konsisten juga terjadi. Maka hampir dijamin bahwa memperbaiki satu bug akan membuat bug lain (menarik ketika bagian tertentu dari spec tidak dilakukan sampai nanti dalam proyek).
sumber
Bayangkan Anda memiliki produk yang lengkap. Kemudian Anda menambahkan sesuatu yang baru, semuanya tampak baik-baik saja, tetapi Anda memecahkan sesuatu yang lain, yang tergantung pada beberapa kode yang Anda ubah untuk membuat fitur baru berfungsi. Bahkan jika Anda tidak mengubah kode apa pun, cukup tambahkan fungsionalitas yang ada, itu mungkin merusak sesuatu yang lain.
Jadi pada dasarnya Anda hampir menjawab sendiri:
Belajarlah untuk mengadaptasi prinsip TDD (setidaknya untuk fitur baru) dan mencoba menguji setiap keadaan yang mungkin terjadi.
Pemrograman pasangan sangat bagus, tetapi tidak selalu "tersedia" (waktu, uang, keduanya ..). Tetapi review kode (oleh kolega Anda misalnya) sekali sehari / minggu / set komit akan sangat membantu juga, terutama, ketika review menyertakan test suite. (Saya merasa sulit untuk tidak menulis bug untuk menguji suite ... kadang-kadang saya harus menguji tes secara internal (cek kewarasanan) :)).
sumber
Katakanlah pengembang A menulis beberapa kode dengan bug. Kode tidak persis apa yang seharusnya dilakukan, tetapi sesuatu yang sedikit berbeda. Pengembang B menulis kode yang mengandalkan kode A melakukan apa yang seharusnya dilakukan, dan kode B tidak bekerja. B menyelidiki, menemukan perilaku yang salah dalam kode A, dan memperbaikinya.
Sementara itu kode pengembang C hanya bekerja dengan benar karena ia mengandalkan perilaku kode A yang salah. Kode A sekarang benar. Dan kode C berhenti bekerja. Yang berarti ketika Anda memperbaiki kode, Anda harus memeriksa dengan sangat hati-hati siapa yang menggunakan kode ini, dan bagaimana perilaku mereka akan berubah dengan kode tetap.
Saya memiliki situasi lain: Beberapa kode bertingkah buruk dan menghentikan fitur sepenuhnya dari bekerja di beberapa situasi X. Jadi saya mengubah perilaku buruk dan membuat fitur berfungsi. Efek samping yang tidak menguntungkan adalah bahwa seluruh fitur memiliki masalah yang signifikan dalam situasi X dan gagal di semua tempat - ini benar-benar tidak diketahui siapa pun karena situasinya belum pernah muncul sebelumnya. Yah, itu sulit.
sumber