Secara umum, yang saya lakukan adalah:
Cobalah untuk mengisolasi masalahnya. Pikirkan apa yang telah berubah ketika bug pertama kali muncul. Di mana Anda bekerja? Bagian mana dari kode yang Anda ubah? 99% bug saya dipecahkan dengan cara ini. Ini biasanya sesuatu yang konyol.
Jika saya menebak di mana masalahnya, perhatikan baik-baik kode yang tampaknya menjadi penyebabnya. Membacanya. Baca dengan keras bahkan. Tanyakan pada diri sendiri: "Apa yang ingin saya capai?" Untuk beberapa jenis masalah: Mungkinkah ada efek samping atau mungkinkah dipengaruhi oleh kode di tempat lain dengan cara yang tidak saya pikirkan?
Coba dengan berbagai cara untuk menganalisis apa yang salah, di mana dan kapan (lihat di bawah).
Jika saya masih tidak memiliki petunjuk, saya memeriksa apakah versi yang lebih lama dari sumber saya memiliki masalah yang sama, coba temukan ketika dalam timeline pengembangan saya masalah pertama kali muncul. Untuk melakukan ini, Anda perlu bekerja dengan sistem kontrol versi yang bagus, seperti git (git memiliki fitur yang disebut bisect untuk debugging semacam ini).
Jika masih tidak tahu, istirahatlah .... itu sebenarnya sering membantu.
Kembali ke papan gambar - tinjau bagaimana program Anda seharusnya bekerja dan apakah itu benar-benar masuk akal.
Ini benar-benar tergantung pada jenis masalah, tetapi dengan asumsi saya memiliki ide umum tentang di mana masalahnya, maka:
Jika saya menduga masalahnya ada di beberapa bagian kode / perubahan terbaru, saya coba dulu untuk menghapus / mengomentari / mengubah atau apa pun untuk menghilangkan bug dengan membuat kode lebih sederhana, dan kemudian mengembalikan kode bermasalah dan mengambil lihat itu.
Jalankan debugger dengan breakpoints (jika mungkin sama sekali) dan lihat bagaimana data saya terlihat berusaha menemukan ketika itu mulai bertindak buruk, untuk mendapatkan ide yang lebih baik dari mana ada yang salah.
bzr qdiff
perintah.Saya mencoba menggunakan test-driven development ( TDD ). Saya menulis tes yang mereplikasi bug, kemudian mencoba untuk mendapatkan tes untuk lulus. Kadang-kadang tindakan menulis tes membantu menemukan bug.
Ini membuat saya keluar dari debugger sebagian besar waktu, dan memberikan tes regresi untuk mencegah memperkenalkan kembali bug.
Beberapa tautan:
sumber
Ada sejumlah definisi untuk kata sains, tetapi sepertinya Anda mungkin merujuk pada apa yang lebih tepat disebut " metode ilmiah ". Metode ilmiah dapat diringkas sebagai mengamati beberapa fenomena (mungkin bug atau perilaku program yang tidak terduga), merumuskan hipotesis atau hipotesis untuk menjelaskan perilaku, dan yang paling mungkin bereksperimen untuk membuktikannya (menulis tes yang mereproduksi masalah dengan andal).
Jenis bug (fenomena) yang dapat terjadi praktis tidak ada habisnya dan beberapa tidak perlu proses yang jelas. Misalnya, kadang-kadang Anda mengamati bug dan Anda langsung tahu apa yang menyebabkannya hanya karena Anda sangat terbiasa dengan kode tersebut. Di waktu lain, Anda tahu bahwa dengan beberapa input (aksi, serangkaian langkah, dll.), Hasil yang salah terjadi (macet, output buruk, dll.). Untuk kasus-kasus itu, seringkali tidak memerlukan banyak pemikiran "ilmiah". Beberapa pemikiran dapat membantu mengurangi ruang pencarian, tetapi metode yang umum adalah hanya dengan menelusuri kode dalam debugger dan melihat di mana semuanya berjalan serba salah.
Namun, situasi yang saya anggap paling menarik dan mungkin layak untuk proses ilmiah adalah ketika Anda menyerahkan beberapa hasil akhir dan diminta untuk menjelaskan bagaimana hal itu terjadi. Contoh nyata dari ini adalah crash dump. Anda dapat memuat crash dump dan mengamati keadaan sistem dan tugas Anda adalah menjelaskan bagaimana keadaannya. Kecelakaan crash (atau inti) dapat menunjukkan pengecualian, kebuntuan, kesalahan internal, atau keadaan "tidak diinginkan" seperti yang didefinisikan oleh pengguna (misalnya, kelesuan). Untuk situasi ini, saya biasanya mengikuti langkah-langkah berikut ini:
Observasi Sempit : Studi informasi langsung di sekitar masalah spesifik jika berlaku. Hal-hal yang jelas di sini adalah tumpukan panggilan, variabel lokal jika Anda bisa melihatnya, garis-garis kode yang mengelilingi masalah. Jenis studi lokasi spesifik ini tidak selalu berlaku. Sebagai contoh, mempelajari sistem "lambat" mungkin tidak memiliki lokasi awal yang jelas seperti ini, tetapi situasi kerusakan atau kesalahan internal kemungkinan akan memiliki titik kepentingan yang segera dan jelas. Salah satu langkah spesifik di sini mungkin menggunakan alat seperti windbg (jalankan! Analisis -v pada crash dump yang dimuat dan lihat apa yang memberitahu Anda).
Pengamatan Luas : Mempelajari bagian lain dari sistem. Periksa status semua utas dalam sistem, lihat informasi global apa pun (jumlah pengguna / operasi / item, transaksi / proses / widget aktif, dll.), Informasi sistem (OS), dll. Jika pengguna memberikan detail eksternal apa pun , pikirkan hal-hal yang berkaitan dengan apa yang telah Anda amati. Misalnya, jika mereka memberi tahu Anda bahwa masalahnya terjadi setiap Selasa sore, tanyakan pada diri sendiri apa artinya itu.
Mengadakan hipotesa: Ini adalah bagian yang benar-benar menyenangkan (dan saya tidak bercanda tentang hal itu menjadi menyenangkan). Ini seringkali membutuhkan banyak pemikiran logis secara terbalik. Sangat menyenangkan untuk memikirkan bagaimana sistem masuk ke kondisi saat ini. Saya menduga ini bagian yang banyak orang anggap sebagai seni. Dan saya kira itu mungkin jika programmer baru saja mulai melemparkan benda-benda secara acak untuk melihat tongkat apa. Tetapi dengan pengalaman, ini bisa menjadi proses yang didefinisikan dengan cukup baik. Jika Anda berpikir sangat logis pada titik ini, sering kali mungkin untuk menentukan set path yang mengarah ke status yang diberikan. Saya tahu bahwa kita dalam keadaan S5. Agar itu terjadi, S4a atau S4b perlu terjadi dan mungkin S3 sebelum S4a, dll. Lebih sering tidak, mungkin ada beberapa item yang dapat mengarah ke keadaan tertentu. Kadang-kadang mungkin membantu untuk menuliskan pada kertas awal alur sederhana atau diagram keadaan atau serangkaian langkah yang berhubungan dengan waktu. Proses aktual di sini akan sangat bervariasi tergantung pada situasinya, tetapi pemikiran serius (dan pemeriksaan ulang pada langkah-langkah sebelumnya) pada saat ini akan sering memberikan satu atau lebih jawaban yang masuk akal. Perhatikan juga bahwa bagian yang sangat penting dari langkah ini adalah untuk menghilangkan hal-hal yang tidak mungkin. Menghapus yang mustahil dapat membantu memangkas ruang solusi (ingat apa yang dikatakan Sherlock Holmes tentang apa yang tersisa setelah Anda menghilangkan yang mustahil). Perhatikan juga bahwa bagian yang sangat penting dari langkah ini adalah untuk menghilangkan hal-hal yang tidak mungkin. Menghapus yang mustahil dapat membantu memangkas ruang solusi (ingat apa yang dikatakan Sherlock Holmes tentang apa yang tersisa setelah Anda menghilangkan yang mustahil). Perhatikan juga bahwa bagian yang sangat penting dari langkah ini adalah untuk menghilangkan hal-hal yang tidak mungkin. Menghapus yang mustahil dapat membantu memangkas ruang solusi (ingat apa yang dikatakan Sherlock Holmes tentang apa yang tersisa setelah Anda menghilangkan yang mustahil).
Eksperimen : Pada tahap ini, cobalah untuk mereproduksi masalah berdasarkan hipotesis yang diturunkan pada langkah sebelumnya. Jika Anda melakukan pemikiran serius pada langkah sebelumnya, ini seharusnya sangat mudah. Terkadang saya "menipu" dan memodifikasi basis kode untuk membantu tes yang diberikan. Sebagai contoh, saya baru-baru ini menyelidiki kecelakaan yang saya simpulkan karena kondisi balapan. Untuk memverifikasinya, saya cukup meletakkan Sleep (500) di antara beberapa baris kode untuk memungkinkan utas lain melakukan hal-hal buruk pada saat yang tepat. Saya tidak tahu apakah ini diizinkan dalam sains "nyata", tetapi sangat masuk akal dalam kode yang Anda miliki.
Jika Anda berhasil mereproduksinya, kemungkinan Anda hampir selesai (semua yang tersisa adalah langkah sederhana untuk memperbaikinya ... tapi itu untuk hari lain). Pastikan untuk memeriksa tes baru ke dalam sistem uji regresi. Dan saya harus menunjukkan bahwa saya bermaksud pernyataan sebelumnya tentang memperbaikinya menjadi sederhana. Menemukan suatu solusi dan mengimplementasikannya membutuhkan kerja keras. Menurut pendapat saya, memperbaiki bug bukan bagian dari proses debugging, melainkan pengembangan. Dan jika perbaikannya sama sekali terlibat, bahwa itu harus memerlukan sejumlah desain dan ulasan.
sumber
Cobalah untuk mengurangi test case. Ketika cukup kecil biasanya lebih mudah untuk menemukan kode yang sesuai yang menyebabkan masalah.
Kemungkinan check-in baru menyebabkan masalah dan build harian sebelumnya baik-baik saja. Dalam hal itu log perubahan Anda dari kontrol sumber akan membantu Anda memutuskan siapa yang akan ditangkap.
Juga, jika Anda menggunakan C / C ++, pertimbangkan menjalankan valgrind atau memurnikan untuk mengisolasi masalah terkait memori.
sumber
Bagian tersulit dari debugging adalah mengisolasi masalah, terutama ketika masalahnya terkubur di bawah beberapa lapisan. Di kampus saya belajar rekaman musik, dan anehnya ada kelas Studio Elektronik yang langsung berlaku di sini. Saya akan menggunakan debugging lingkungan studio sebagai ilustrasi dari proses debugging sistematis.
Kode debug sebenarnya tidak terlalu berbeda. Debugging jauh lebih mudah ketika kode melempar pengecualian. Anda dapat melacak mundur dari jejak tumpukan pengecualian itu dan mengatur titik istirahat di posisi kunci. Biasanya hanya setelah Anda menetapkan variabel, atau pada baris yang memanggil metode yang melempar pengecualian. Anda mungkin menemukan bahwa satu atau beberapa nilai tidak benar. Jika itu tidak benar (nol ketika seharusnya tidak ada, atau nilainya di luar kisaran), maka ini merupakan proses menemukan mengapa itu tidak benar. Titik istirahat dalam IDE setara dengan titik uji elektronik (dirancang untuk probe meter untuk memeriksa rangkaian).
Sekarang, begitu saya telah melalui bagian sulit menemukan di mana masalah saya yang sebenarnya, saya akan menulis beberapa unit test untuk memeriksanya di masa depan.
sumber
Dengan bug jahat yang saya susah payah lacak pada sore hari, strategi saya yang paling efektif adalah berdiri dan berjalan pergi selama beberapa menit. Biasanya ide-ide baru tentang sumber kesalahan yang mungkin mulai mengalir setelah hanya 30 detik.
sumber
Untuk pendekatan yang lebih praktis:
Jika bug terkait dengan pengecualian tidak tertangani - lihat jejak tumpukan. Referensi kosong, indeks di luar batas, dll. Dan pengecualian yang Anda tentukan sendiri adalah yang paling umum, Anda dapat menetapkan bug ini untuk junior dev, yang mungkin mudah dan exp pembelajaran yang bagus.
Jika itu tidak terjadi pada setiap mesin, itu mungkin suatu bentuk kondisi ras / masalah threading. Ini sangat menyenangkan untuk dilacak, letakkan programmer senior yang bosan di atasnya. Banyak penebangan, pengetahuan yang baik, dan alat yang bagus untuk menyelesaikan ini
Kelas bug besar lainnya adalah ketika tim pengujian atau klien tidak menyukai perilaku tertentu. Misalnya, mereka tidak suka Anda memutuskan untuk menampilkan ID pengguna atau ketika mencari Anda tidak mendapatkan pelengkapan otomatis. Ini adalah bug asli, pertimbangkan memiliki manajemen produk yang lebih baik dan pengembang dengan pandangan yang lebih luas. Perlu waktu yang relatif singkat bagi pengembang untuk "memperbaiki" ini jika ia membangun sistem dengan mempertimbangkan ekspansi.
80% dari semua bug lainnya diselesaikan dengan memiliki sistem logging yang baik dan mengumpulkan cukup info untuk menyelesaikannya. Gunakan penelusuran bawaan dengan beberapa tingkat, sistem pencatatan yang rumit seperti Log4Net / Log4J
bug kinerja adalah kategori mereka sendiri, aturan golder di sini adalah "ukur dulu, perbaiki nanti!", dan Anda akan terkejut melihat berapa banyak pengembang yang hanya menebak di mana masalahnya dan langsung masuk untuk memperbaikinya hanya untuk melihat kemudian hanya penurunan 3-4% dalam waktu respons.
sumber
Saya memiliki dua pendekatan:
Divide and Conquer
Paradigma.Pendekatan ini telah banyak membantu saya.
sumber