Apa yang bisa menjadi penyebab bug baru muncul di tempat lain ketika bug yang diketahui diselesaikan?

14

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
Arseni Mourzenko
sumber
14
Ah, pola desain "gelombang cascading kegagalan" yang bagus. :-)
Brian Knoblauch
1
Saya menyamakannya dengan gelembung di selembar kontak. Dorong ke bawah, itu muncul di tempat lain. Lebih baik saya coding, semakin kurang saya lihat
JohnC
2
Di samping catatan, saya memiliki persis pada sistem yang tertanam. Saya menambahkan panggilan fungsi untuk memperbaiki masalah. Pemanggilan fungsi itu terlalu banyak untuk stack (mikrokontroler tidak memiliki deteksi stackoverflow) dan karenanya ia menulis beberapa hal acak di tempat lain ke memori, yang tentu saja memecahkan sesuatu di suatu tempat yang sama sekali berbeda. Jadi, hal ini BISA terjadi pada basis kode kecil dengan hanya satu pengembang dan arsitektur yang baik.
Rising Darkness
... dan itu adalah mimpi buruk untuk debug.
RisingDarkness

Jawaban:

38

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.

Karl Bielefeldt
sumber
15
ini dikombinasikan dengan pengujian regresi yang buruk atau tidak ada sama sekali
Ryathal
3
Benar, @Ryathal, meskipun pengujian regresi tidak akan mencegah bug semacam itu, beri tahu Anda tentang mereka lebih awal.
Karl Bielefeldt
Jika Anda segera mengetahuinya (mis. Dalam hitungan menit membuat bug) maka Anda dapat membatalkan perubahan dan berpura-pura tidak pernah terjadi.
bdsl
14

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.

Giorgio
sumber
7

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.

ddyer
sumber
5

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.

Mike B
sumber
5

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 memcpybug dari Linus Torvalds di mana perubahan implementasinya mengekspos (tidak menyebabkan) bug pada klien yang digunakan memcpydi tempat-tempat di mana mereka seharusnya digunakan memmovedengan sumber dan tujuan yang tumpang tindih.


sumber
4

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.

Ramhound
sumber
0

Tingkatkan luas rejimen tes otomatis Anda. SELALU menjalankan uji penuh sebelum melakukan perubahan kode. Dengan begitu, Anda akan mendeteksi efek buruk perubahan Anda.

Stephen Gross
sumber
0

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).

ccoakley
sumber
0

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:

  • kopling longgar
  • kurangnya tes

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) :)).

Dalibor Filus
sumber
0

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.

gnasher729
sumber