← Back to blog

Debugging Tanpa Terlalu Banyak Menebak

DebuggingEngineeringObservabilityProblem Solving

Ketika menemukan bug, reaksi pertama saya sering ingin langsung mengubah kode yang terlihat mencurigakan. Kadang berhasil, tetapi lebih sering hanya memindahkan gejala atau menambah masalah baru.

Debugging terasa lebih tenang ketika diperlakukan sebagai proses mempersempit kemungkinan. Bukan mencari siapa yang salah, melainkan mencari titik pertama ketika perilaku sistem berbeda dari yang diharapkan.

Tulis gejalanya dengan spesifik

Kalimat “fitur login rusak” masih terlalu luas. Deskripsi yang lebih berguna misalnya:

Setelah token akses kedaluwarsa, request pertama mendapatkan 401, refresh token berhasil, tetapi request awal tidak dikirim ulang.

Deskripsi tersebut sudah memberi batas pada kondisi, urutan kejadian, dan hasil yang salah. Semakin jelas gejalanya, semakin sedikit bagian sistem yang perlu diperiksa.

Beberapa informasi awal yang biasanya saya catat:

  • Perilaku yang diharapkan dan yang benar-benar terjadi
  • Environment tempat bug muncul
  • Waktu kejadian dan identitas request
  • Langkah paling pendek untuk mereproduksi
  • Apakah masalah selalu terjadi atau hanya sesekali
  • Perubahan terakhir yang mungkin berkaitan

Pastikan bug dapat diulang

Reproduksi yang stabil mengubah debugging dari permainan tebak-tebakan menjadi eksperimen. Kurangi langkah sampai tersisa contoh paling kecil yang masih gagal.

Jika bug hanya muncul sesekali, cari variabel yang berubah:

  • Kondisi jaringan
  • Urutan request
  • State pengguna
  • Waktu dan timezone
  • Ukuran data
  • Versi aplikasi atau browser
  • Proses yang berjalan bersamaan

Jangan mengubah banyak variabel sekaligus. Satu perubahan kecil memberi informasi lebih jelas tentang penyebab masalah.

Ikuti aliran data

Untuk masalah yang melewati beberapa lapisan, saya mencoba mengikuti satu nilai dari awal sampai akhir:

input pengguna
-> state UI
-> request API
-> handler backend
-> database
-> response
-> tampilan

Periksa bentuk dan nilai data pada setiap batas. Titik pertama yang berbeda dari harapan biasanya lebih penting daripada tempat error akhirnya terlihat.

Misalnya, pesan “data tidak ditemukan” pada UI belum tentu berarti database kosong. Bisa jadi ID berubah menjadi string kosong ketika form diserialisasi.

Gunakan log yang menjawab pertanyaan

Menambahkan console.log('masuk sini') dapat membantu sebentar, tetapi cepat menjadi bising. Log yang lebih berguna menyertakan context:

logger.info('Refreshing access token', {
  requestId,
  userId,
  tokenExpiresAt
});

Hindari mencatat password, token, isi percakapan pribadi, atau data sensitif lainnya. Observability yang baik tetap perlu menjaga privasi.

Correlation ID sangat membantu ketika satu aksi melewati frontend, API, worker, dan service lain. Tanpanya, potongan log yang benar bisa terlihat seperti kejadian yang tidak berkaitan.

Bandingkan kondisi berhasil dan gagal

Ketika penyebab belum terlihat, ambil satu contoh berhasil dan satu contoh gagal. Bandingkan input, header, response, state, dan urutan waktunya.

Pertanyaan sederhananya:

Apa perbedaan terkecil yang hanya muncul pada kasus gagal?

Teknik ini sering menemukan masalah konfigurasi, permission, format tanggal, cache, atau race condition yang sulit terlihat jika hanya membaca kode.

Buat hipotesis yang dapat dibantah

Hipotesis seperti “mungkin cache” terlalu kabur. Buat prediksi yang dapat diuji:

Jika response lama berasal dari cache browser, menonaktifkan cache akan membuat data terbaru muncul tanpa perubahan pada server.

Jika prediksi salah, coret kemungkinan tersebut. Hasil negatif tetap berguna karena mempersempit ruang pencarian.

Perbaiki penyebab dan tambahkan penjaga

Setelah menemukan penyebab, perbaikannya sebaiknya mencakup cara mencegah masalah yang sama kembali. Penjaga itu dapat berupa:

  • Regression test
  • Runtime validation
  • Constraint database
  • Error message yang lebih jelas
  • Metric atau alert
  • Dokumentasi untuk konfigurasi yang mudah terlewat

Test terbaik biasanya mereproduksi bug sebelum perbaikan dan lulus setelah perbaikan diterapkan.

Kesimpulan

Debugging yang efektif tidak selalu terlihat cepat pada beberapa menit pertama. Waktu tersebut digunakan untuk membangun pemahaman agar perubahan berikutnya lebih tepat.

Saya masih sesekali menebak. Bedanya, saya berusaha mengubah tebakan menjadi hipotesis kecil yang dapat diuji, lalu membiarkan bukti menentukan langkah berikutnya.