Debugging Checklist — Debugging

Debugging Checklist Checklist sistematis yang bisa kamu ikuti setiap kali menemui bug. Simpan halaman ini sebagai referensi! Step 1: Reproduksi Bug Bisa kamu…

Debugging checklist adalah urutan langkah yang selalu sama setiap kali ketemu bug, supaya kamu gak lompat-lompat menebak. Bayangin montir yang menangani motor mogok. Montir yang baik gak langsung bongkar mesin. Dia nyalakan dulu motornya untuk merasakan gejalanya, lalu cek bensin, busi, dan aki satu per satu, dari yang paling murah dicek, sampai ketemu biangnya. Setelah diperbaiki, dia tes jalan sekali lagi.

🧪 Tebakan cepat: subtotal bernilai 105000 (number), dan ongkir dari API bernilai "10000" (string). subtotal + ongkir hasilnya 115000, atau sesuatu yang lain? Tebak dulu, jawabannya ada di bagian "Langkah 4: periksa nilai dan tipenya".

Bug yang kita kejar

Di Lab, tombol Bayar menampilkan Total: Rp10500010000, padahal harusnya Rp115.000 (Buku 45.000 x 2, Pensil 5.000 x 3, ongkir 10.000).

const keranjang = [
  { nama: "Buku", harga: 45000, qty: 2 },
  { nama: "Pensil", harga: 5000, qty: 3 },
];

async function hitungBayar() {
  const subtotal = keranjang.reduce((sum, item) => sum + item.harga * item.qty, 0);
  const res = await fetch("/api/ongkir?kota=bandung");
  const { ongkir } = await res.json();
  return subtotal + ongkir;
}

Kita ikuti checklist-nya dari langkah pertama.

Langkah 1 sampai 3: reproduksi, Console, Network

  1. Reproduksi. Catat langkah persisnya, hasil yang diharapkan, dan hasil yang terjadi. Di sini: buka keranjang, klik Bayar; diharapkan Rp115.000, yang muncul Rp10500010000, dan terjadi setiap kali. Bug yang bisa dimunculkan lagi kapan saja jauh lebih mudah diburu. Kalau cuma kadang-kadang, catat kondisinya: browser, ukuran layar, user yang login, data tertentu.
  2. Baca Console. Ada error merah? Kalau ada, baca jenis, pesan, dan stack trace-nya (pelajaran Membaca Error Messages). Di bug ini Console bersih. Itu juga petunjuk: kodenya gak crash, jadi masalahnya di logika atau data.
  3. Cek Network. Filter Fetch/XHR, klik request-nya, lalu periksa status dan tab Response. Di sini GET /api/ongkir?kota=bandung berstatus 200, dan response-nya {"ongkir":"10000"}. Perhatikan tanda kutipnya: ongkir dikirim sebagai teks, bukan angka.

Langkah 4: periksa nilai dan tipenya

Jangan cuma mencetak nilainya; cetak juga tipenya. console.log(ongkir) mencetak 10000, sama persis dengan angka. Helper kecil dari latihan membedakannya:

debugValue("subtotal", subtotal); // [subtotal] type:number val:105000
debugValue("ongkir", ongkir);     // [ongkir] type:string val:10000

Ketemu: ongkir itu string. Di JavaScript, + dengan salah satu sisi berupa string bukan penjumlahan, tapi penyambungan teks: 105000 + "10000" menjadi "10500010000". Jadi hasilnya bukan 115000. Itu jawaban tebakannya.

Cara lain untuk langkah ini: console.log({ ongkir }) mencetak nama dan nilainya sekaligus (string tampil dengan tanda kutip), atau pasang breakpoint dan baca Scope (pelajaran Breakpoints & Stepping).

Langkah 5 sampai 7: isolasi, perbaiki, kunci dengan test

  1. Isolasi. Kecilkan masalahnya sampai tinggal intinya. Satu baris console.log(105000 + "10000") sudah memunculkan bug yang sama, tanpa keranjang, tanpa fetch. Kalau belum tahu bagian mana yang salah, matikan separuh kode atau pindahkan separuh data, lalu cek apakah bug-nya masih ada.
  2. Perbaiki di sumbernya. Ubah teks jadi angka sebelum dijumlah: return subtotal + Number(ongkir);. Hasilnya 115000. Lebih baik lagi, minta API mengirim ongkir sebagai number.
  3. Kunci dengan regression test. Tulis tes yang gagal kalau bug yang sama muncul lagi. Langkah ini paling sering dilewatkan, padahal tanpa tes, perubahan kecil bulan depan bisa diam-diam mengembalikan bug yang sama.
function hitungTotal(subtotal, ongkir) {
  return subtotal + Number(ongkir);
}

console.assert(hitungTotal(105000, "10000") === 115000, "ongkir string harus dijumlah sebagai angka");

console.assert(kondisi, pesan) diam saja kalau kondisinya true, dan mencetak Assertion failed: pesan kalau false.

Kalau masih buntu: rubber duck dan minta bantuan

Latihan: helper debugValue

Di latihan kamu menulis debugValue(label, value): mencetak keterangan nilai beserta tipenya, lalu mengembalikan value apa adanya.

Panggilan Yang dicetak
debugValue("user", null) [user] NULL
debugValue("config", undefined) [config] UNDEFINED
debugValue("items", [1, 2, 3]) [items] Array(3)
debugValue("data", { a: 1, b: 2, c: 3 }) [data] Object{3}
debugValue("count", 42) [count] type:number val:42
debugValue("name", "Budi") [name] type:string val:Budi

Urutan pengecekannya menentukan hasil:

🎯 Pohon keputusan singkat

Ada error merah di Console?
  ya   -> baca jenis, pesan, dan baris paling atas stack trace
  gak  -> cek Network: ada request gagal (4xx/5xx) atau response aneh?
          ya  -> periksa URL, method, header, dan body-nya
          gak -> data benar tapi tampilan salah? cek Elements dan CSS
                 data salah? periksa nilai dan tipenya, telusuri dari sumbernya
Bug cuma kadang-kadang?
  -> curigai urutan async (await yang lupa), cache (hard reload), atau data tertentu

⚠️ Jebakan yang sering ketemu

TL;DR: Ikuti urutan yang sama tiap kali: reproduksi (langkah, harapan, kenyataan), baca Console, cek Network (status dan response), periksa nilai beserta tipenya, isolasi sampai sekecil mungkin, perbaiki di sumbernya, lalu kunci dengan regression test supaya bug-nya gak kembali. Di contoh, Console bersih, Network menunjukkan "ongkir":"10000" sebagai string, dan 105000 + "10000" menyambung teks jadi "10500010000"; Number(ongkir) memperbaikinya jadi 115000. Kalau buntu, jelaskan kodemu ke bebek karet (rubber duck debugging). debugValue mencetak [label] NULL, [label] UNDEFINED, [label] Array(N), [label] Object{N}, atau [label] type:X val:Y, mengecek null dan array sebelum object, dan mengembalikan nilainya.

Yang akan kamu pelajari