Bab 2: Kualitas Kode

10 menit baca

"Kode yang bagus itu bukan cuma jalan — tapi bisa dibaca orang lain tanpa pengen nangis."

Bab ini bukan soal bikin fitur baru. Ini soal kebiasaan yang bikin kamu jadi programmer yang dihargai tim. Kode yang rapi, bisa di-debug, dan teruji otomatis.


2.1 Debugging di Browser

Apa Itu Debugging?

Debugging = proses cari dan benerin error di kode kamu.

Analogi: Bayangin kamu masak, rasanya aneh. Debugging itu kayak nyicip satu-satu bahan — "oh, kebanyakan garam di langkah ke-3."

Developer Tools (DevTools)

Setiap browser modern punya "dapur rahasia" buat developer. Di Chrome:

  • Buka: Tekan F12 atau Ctrl + Shift + I
  • Panel Sources: Tempat kamu lihat dan debug kode

Breakpoint — Titik Berhenti

Breakpoint = titik di mana kamu bilang ke browser: "Berhenti di sini, aku mau periksa."

Cara pasang: Klik nomor baris di panel Sources.

javascript
function hitungDiskon(harga, persen) {
  let potongan = harga * persen / 100;
  let hargaAkhir = harga - potongan; // pasang breakpoint di sini
  return hargaAkhir;
}

Waktu eksekusi berhenti di breakpoint, kamu bisa:

  • Lihat nilai variabel saat itu (hover mouse di atas variabel)
  • Cek Call Stack (urutan fungsi yang dipanggil)
  • Jalankan kode baris per baris

Perintah debugger

Selain klik manual, kamu bisa tulis debugger; langsung di kode:

javascript
function hitungDiskon(harga, persen) {
  let potongan = harga * persen / 100;
  debugger; // browser akan berhenti di sini
  let hargaAkhir = harga - potongan;
  return hargaAkhir;
}

⚠️ debugger cuma aktif kalau DevTools terbuka. Kalau ditutup, diabaikan.

Tombol Navigasi Debugging

TombolFungsiHotkey
▶ ResumeLanjut sampai breakpoint berikutnyaF8
⤵ StepJalankan 1 baris, masuk ke dalam fungsiF9
⤴ Step OverJalankan 1 baris, SKIP isi fungsiF10
⬆ Step OutKeluar dari fungsi saat iniShift+F11

console.log — Debugging Sederhana

Kalau males buka DevTools, cara paling gampang:

javascript
for (let i = 0; i < 5; i++) {
  console.log("Iterasi ke:", i);
}

Kapan pakai apa?

  • console.log → cek cepat, masalah simpel
  • Breakpoint → masalah kompleks, perlu lihat alur eksekusi

💡 Tips Pro

  1. Jangan hapus console.log satu-satu — pakai Ctrl+H replace semua
  2. Pakai console.table() untuk lihat array/object dalam bentuk tabel
  3. console.error() dan console.warn() buat bedain jenis pesan
🎯Challenge

Buat fungsi cekUmur(umur) yang return "anak", "remaja", atau "dewasa". Pasang debugger di dalamnya, lalu panggil dengan berbagai nilai. Amati bagaimana variabel berubah di DevTools.

javascript
function cekUmur(umur) {
  debugger;
  if (umur < 12) {
    return "anak";
  } else if (umur < 18) {
    return "remaja";
  } else {
    return "dewasa";
  }
}

cekUmur(15); // coba ganti-ganti nilainya

2.2 Gaya Penulisan Kode (Coding Style)

Kenapa Gaya Kode Penting?

Analogi: Tulisan tangan yang rapi vs cakar ayam. Dua-duanya bisa dibaca (mungkin), tapi yang rapi bikin orang senang bacanya.

Kode itu lebih sering dibaca daripada ditulis. Kamu nulis sekali, tapi kamu (dan orang lain) baca berkali-kali.

Aturan Dasar

1. Kurung Kurawal — Gaya "Mesir"

javascript
// ✅ BENAR — kurung buka di baris yang sama
if (kondisi) {
  lakukanIni();
}

// ❌ SALAH — kurung buka di baris baru (bukan standar JS)
if (kondisi)
{
  lakukanIni();
}

Kenapa? Karena 99% project JavaScript pakai gaya ini. Ikuti konvensi.

2. Spasi dan Indentasi

javascript
// ✅ BENAR — ada spasi, mudah dibaca
function hitungLuas(panjang, lebar) {
  let luas = panjang * lebar;
  return luas;
}

// ❌ SALAH — rapet, susah dibaca
function hitungLuas(panjang,lebar){
let luas=panjang*lebar;
return luas;
}

Aturan:

  • Indentasi: 2 spasi (standar modern) atau 4 spasi
  • Spasi setelah keyword: if (, for (, function (
  • Spasi di sekitar operator: a = b + c, bukan a=b+c

3. Panjang Baris — Maksimal 80-120 Karakter

Kalau terlalu panjang, pecah:

javascript
// ❌ Terlalu panjang
if (umur >= 18 && punyaKTP === true && sudahDaftar === true && tidakDiblokir === true) {

// ✅ Dipecah
if (
  umur >= 18 &&
  punyaKTP === true &&
  sudahDaftar === true &&
  tidakDiblokir === true
) {
  // ...
}

4. Baris Kosong — Pemisah Logika

javascript
function prosesOrder(order) {
  // Validasi
  let isValid = cekOrder(order);

  // Hitung total
  let total = hitungTotal(order.items);

  // Kirim
  kirimOrder(order, total);
}

Baris kosong = paragraf baru. Bikin kode "bernafas".

5. Hindari Nesting Terlalu Dalam

javascript
// ❌ Nesting dalam — susah dibaca
function cekAkses(user) {
  if (user) {
    if (user.umur >= 18) {
      if (user.verified) {
        return true;
      }
    }
  }
  return false;
}

// ✅ Early return — lebih flat
function cekAkses(user) {
  if (!user) return false;
  if (user.umur < 18) return false;
  if (!user.verified) return false;

  return true;
}

Prinsip: Return lebih awal untuk kasus-kasus "gagal", sisakan kode utama di bawah.

6. Titik Koma (Semicolon)

javascript
// ✅ Selalu pakai titik koma
let nama = "Budi";
console.log(nama);

// ❌ Tanpa titik koma — bisa bikin bug tersembunyi
let nama = "Budi"
console.log(nama)

JavaScript punya "Automatic Semicolon Insertion" (ASI), tapi kadang dia salah tebak. Lebih aman tulis sendiri.

Style Guide Populer

Style GuideDipakai Oleh
AirbnbBanyak startup
GoogleGoogle
StandardJSTanpa titik koma

Untuk pemula: ikuti Airbnb — paling populer dan detail.

Linter — Penjaga Otomatis

Linter = tool yang otomatis cek gaya kode kamu dan kasih peringatan.

Yang paling populer: ESLint

bash
# Install
npm install -g eslint

# Jalankan
eslint namaFile.js

ESLint bakal bilang: "Hei, baris 5 kurang spasi!" atau "Variabel x dideklarasi tapi nggak dipakai."

💡 Kebanyakan code editor (VS Code) punya extension ESLint yang langsung kasih garis merah/kuning waktu kamu nulis.

🎯Challenge

Perbaiki kode berikut sesuai aturan coding style yang benar:

javascript
// PERBAIKI INI:
function hitung(x,n)
{
  let result=1;
  for(let i=0;i<n;i++) {result*=x;}
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
  alert(`Pangkat ${n} tidak didukung, masukkan bilangan bulat positif`);
}
else
{
  alert(hitung(x,n))
}

2.3 Komentar yang Baik

Komentar Buruk vs Komentar Baik

Analogi: Komentar itu kayak catatan di pinggir buku. Kalau catatannya cuma ngulang isi buku — ngapain? Yang berguna itu catatan yang kasih insight tambahan.

❌ Komentar Buruk — Menjelaskan "Apa"

javascript
// Tambahkan 1 ke i
i++;

// Cek apakah umur lebih dari 18
if (umur > 18) { ... }

// Loop dari 0 sampai 9
for (let i = 0; i < 10; i++) { ... }

Ini semua nggak perlu. Kodenya sudah jelas sendiri.

Prinsip: Kalau kode butuh komentar untuk dipahami, mungkin kodenya yang harus ditulis ulang lebih jelas.

✅ Komentar Baik — Menjelaskan "Kenapa"

javascript
// Pakai setTimeout 0ms untuk jalankan setelah DOM selesai render
// (tanpa ini, elemen belum ada di halaman)
setTimeout(() => {
  initSlider();
}, 0);

// Format harga tanpa library karena Intl.NumberFormat
// belum support di target browser kita (IE11)
function formatHarga(angka) {
  return angka.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}

Resep: Ganti Komentar dengan Fungsi

javascript
// ❌ Pakai komentar untuk jelaskan blok kode
// Cek apakah bilangan prima
for (let j = 2; j < n; j++) {
  if (n % j === 0) return false;
}

// ✅ Buat fungsi — nama fungsi = komentar
function isPrima(n) {
  for (let j = 2; j < n; j++) {
    if (n % j === 0) return false;
  }
  return true;
}

Kode yang self-descriptive (menjelaskan dirinya sendiri) > kode + komentar.

Kapan HARUS Pakai Komentar

  1. Arsitektur keseluruhan — gambaran besar sistem
  2. Dokumentasi fungsi (JSDoc) — parameter, return value
  3. Keputusan yang tidak obvious — "kenapa pakai cara ini, bukan cara itu"
  4. Hack/workaround — "ini workaround untuk bug di library X"

JSDoc — Dokumentasi Formal

javascript
/**
 * Hitung luas lingkaran.
 *
 * @param {number} radius - Jari-jari lingkaran
 * @returns {number} Luas lingkaran
 */
function luasLingkaran(radius) {
  return Math.PI * radius * radius;
}

JSDoc berguna karena:

  • Editor bisa kasih autocomplete
  • Bisa di-generate jadi dokumentasi HTML
  • Tim baru langsung paham tanpa baca isi fungsi
🎯Challenge

Lihat kode ini. Hapus komentar yang tidak perlu, dan tambahkan komentar yang berguna:

javascript
// Fungsi untuk menghitung diskon
function hitungDiskon(harga, member) {
  // Cek apakah member
  if (member) {
    // Kalikan harga dengan 0.8
    return harga * 0.8;
  }
  // Return harga asli
  return harga;
}

2.4 Kode Ninja (Anti-Pattern)

⚠️ INI ADALAH CONTOH BURUK

Bab ini sengaja ditulis sarkastis oleh javascript.info. Semua "tips" di bawah ini adalah hal yang JANGAN kamu lakukan. Tujuannya: supaya kamu bisa mengenali kode buruk saat melihatnya.

❌ Variabel 1 Huruf

javascript
// BURUK — apa itu a, b, c?
let a = getUser();
let b = a.name;
let c = calculateAge(a.birthDate);

// BAIK — jelas
let user = getUser();
let userName = user.name;
let userAge = calculateAge(user.birthDate);

❌ Singkatan Berlebihan

javascript
// BURUK
let brsr = navigator.userAgent;
let lst = document.querySelectorAll("li");

// BAIK
let browserInfo = navigator.userAgent;
let listItems = document.querySelectorAll("li");

❌ Nama Terlalu Abstrak

javascript
// BURUK — "data" bisa apa aja
let data = fetchUsers();
let data2 = processData(data);
let item = data2[0];

// BAIK — spesifik
let users = fetchUsers();
let activeUsers = filterActive(users);
let firstActiveUser = activeUsers[0];

❌ Reuse Variabel untuk Hal Berbeda

javascript
// BURUK — `temp` berubah makna
let temp = getUserInput();
temp = parseInt(temp);
temp = temp * 2;
temp = `Hasil: ${temp}`;

// BAIK — variabel baru untuk tiap tahap
let input = getUserInput();
let angka = parseInt(input);
let hasil = angka * 2;
let pesan = `Hasil: ${hasil}`;

❌ Fungsi dengan Side Effect Tersembunyi

javascript
// BURUK — nama "cek" tapi ternyata juga mengubah data
function cekEmail(email) {
  if (!email.includes("@")) {
    showError("Email tidak valid"); // side effect!
    logAttempt(email); // side effect!
    return false;
  }
  return true;
}

// BAIK — pisahkan tanggung jawab
function isEmailValid(email) {
  return email.includes("@");
}

// Panggil terpisah
if (!isEmailValid(email)) {
  showError("Email tidak valid");
  logAttempt(email);
}

Prinsip Utama

PrinsipArtinya
Nama deskriptifVariabel/fungsi harus jelas tujuannya dari namanya
Satu fungsi, satu tugasJangan campur validasi + tampilan + logging
Jangan reuse variabelBikin variabel baru, bukan timpa yang lama
Hindari singkatanKecuali yang sudah universal (i, j untuk loop)
🎯Challenge

Refactor kode "ninja" ini jadi kode yang bersih:

javascript
function f(a, b) {
  let d = a - b;
  if (d < 0) d = -d;
  let r = d > 10;
  return r;
}

Ganti nama variabel dan fungsi supaya jelas tujuannya.


2.5 Testing Otomatis dengan Mocha

Kenapa Perlu Testing?

Analogi: Kamu bikin kue. Setiap kali ubah resep, kamu harus cicipi lagi. Tapi kalau resepnya makin kompleks (100 variasi), nggak mungkin cicipi semua manual tiap kali.

Testing otomatis = robot yang cicipi semua variasi buat kamu.

Masalah Tanpa Testing

  1. Kamu fix bug A → tanpa sadar, fitur B jadi rusak
  2. Kamu takut ubah kode lama → kode jadi "museum" yang nggak ada yang berani sentuh
  3. Kamu manual test → pasti ada yang kelewat

BDD — Behavior Driven Development

BDD = tulis spesifikasi perilaku dulu, baru tulis kodenya.

Spec itu 3-in-1:

  • Test — bukti kode jalan benar
  • Dokumentasi — jelaskan apa yang fungsi lakukan
  • Contoh — cara pakai fungsi

Struktur Test

javascript
describe("namaFungsi", function() {

  it("deskripsi perilaku yang diharapkan", function() {
    assert.equal(hasilAktual, hasilYangDiharapkan);
  });

});

Penjelasan:

  • describe = "Aku mau tes fungsi ini"
  • it = "Dalam kasus ini, hasilnya harus begini"
  • assert.equal = "Cek apakah A sama dengan B"

Contoh Nyata

Kita mau bikin fungsi pangkat(x, n) yang menghitung x pangkat n:

javascript
describe("pangkat", function() {

  it("2 pangkat 3 = 8", function() {
    assert.equal(pangkat(2, 3), 8);
  });

  it("3 pangkat 2 = 9", function() {
    assert.equal(pangkat(3, 2), 9);
  });

  it("5 pangkat 1 = 5", function() {
    assert.equal(pangkat(5, 1), 5);
  });

});

Alur Kerja BDD

1. Tulis spec (test) → test GAGAL (belum ada kode) 2. Tulis implementasi minimal → test LULUS 3. Tambah test baru → test GAGAL 4. Perbaiki implementasi → test LULUS 5. Ulangi sampai selesai

Ini namanya Red-Green cycle: Merah (gagal) → Hijau (lulus) → Tambah test → Merah lagi → ...

Tools yang Dipakai

ToolFungsi
MochaFramework test — menyediakan describe, it
ChaiLibrary assertion — menyediakan assert.equal, dll
SinonSpy/mock — untuk test lanjutan

Prinsip: Satu Test, Satu Hal

javascript
// ❌ BURUK — 3 cek dalam 1 test
it("pangkat bekerja", function() {
  assert.equal(pangkat(2, 3), 8);
  assert.equal(pangkat(3, 4), 81);
  assert.equal(pangkat(5, 2), 25);
});

// ✅ BAIK — terpisah, kalau gagal langsung tahu yang mana
it("2 pangkat 3 = 8", function() {
  assert.equal(pangkat(2, 3), 8);
});

it("3 pangkat 4 = 81", function() {
  assert.equal(pangkat(3, 4), 81);
});

Kenapa? Kalau test pertama gagal di versi "buruk", kamu nggak tahu apakah test ke-2 dan ke-3 juga gagal.

Nested Describe

javascript
describe("pangkat", function() {

  describe("x pangkat 3", function() {
    it("2 pangkat 3 = 8", function() {
      assert.equal(pangkat(2, 3), 8);
    });

    it("3 pangkat 3 = 27", function() {
      assert.equal(pangkat(3, 3), 27);
    });
  });

  describe("kasus error", function() {
    it("pangkat negatif = NaN", function() {
      assert.isNaN(pangkat(2, -1));
    });
  });

});

before/after — Setup & Cleanup

javascript
describe("database test", function() {

  before(function() {
    // Jalan SEKALI sebelum semua test
    connectDB();
  });

  after(function() {
    // Jalan SEKALI setelah semua test
    disconnectDB();
  });

  beforeEach(function() {
    // Jalan sebelum SETIAP test
    clearTestData();
  });

  it("bisa simpan user", function() { ... });
  it("bisa hapus user", function() { ... });
});
🎯Challenge

Tulis spec (test) untuk fungsi isGenap(n) yang return true kalau n genap, false kalau ganjil. Tulis minimal 4 test case termasuk edge case (0, angka negatif).

javascript
// Tulis spec-nya dulu:
describe("isGenap", function() {
  // ... tulis it() blocks di sini
});

// Baru tulis implementasinya:
function isGenap(n) {
  // ... kode kamu
}

2.6 Polyfill dan Transpiler

Masalah: JavaScript Terus Berkembang

JavaScript dapat fitur baru tiap tahun. Tapi browser lama nggak paham fitur baru.

Analogi: Bahasa Indonesia dapat kata baru tiap tahun (contoh: "ghosting", "healing"). Kakek-nenek mungkin nggak paham. Kamu perlu "terjemahkan" ke bahasa yang mereka mengerti.

Transpiler — Penerjemah Sintaks

Transpiler = tool yang ubah kode modern jadi kode lama yang browser jadul bisa pahami.

javascript
// Kode modern (pakai ??)
let tinggi = tinggi ?? 100;

// Setelah di-transpile (bisa jalan di browser lama)
let tinggi = (tinggi !== undefined && tinggi !== null) ? tinggi : 100;

Transpiler paling populer: Babel

Cara kerjanya:

  1. Kamu tulis kode modern
  2. Babel baca kode kamu
  3. Babel tulis ulang pakai sintaks lama
  4. Kode hasil transpile yang di-deploy ke server

Polyfill — Penambah Fungsi yang Hilang

Kalau masalahnya bukan sintaks tapi fungsi yang belum ada di browser lama:

javascript
// Math.trunc belum ada di browser lama
// Polyfill = kita bikin sendiri implementasinya

if (!Math.trunc) {
  Math.trunc = function(angka) {
    return angka < 0 ? Math.ceil(angka) : Math.floor(angka);
  };
}

Polyfill = kode yang "mengisi lubang" — menambahkan fungsi yang seharusnya ada tapi belum di-support.

Library polyfill populer: core-js

Perbedaan Transpiler vs Polyfill

TranspilerPolyfill
MenanganiSintaks baru (??, ?., arrow function)Fungsi baru (Array.includes, Promise)
Cara kerjaTulis ulang kodeTambah implementasi fungsi
Kapan jalanSebelum deploy (build time)Saat kode dijalankan (runtime)
Contoh toolBabelcore-js

Workflow Modern

Kode Modern (ES2024) ↓ [Babel] ← transpile sintaks ↓ [core-js] ← polyfill fungsi ↓ Kode yang jalan di semua browser

Biasanya ini diatur otomatis pakai bundler seperti Webpack atau Vite.

Kapan Kamu Perlu Peduli Ini?

  • Sekarang (belajar): Belum perlu. Fokus belajar JavaScript modern dulu.
  • Nanti (kerja/project nyata): Penting banget. Kamu harus pastikan kode jalan di browser target user.

💡 Tips

  1. Selalu tulis kode modern — biar transpiler yang urus kompatibilitas
  2. Cek support fitur di caniuse.com
  3. Chrome biasanya paling update — cocok buat development
🎯Challenge

Tulis polyfill sederhana untuk fungsi String.prototype.includes (cek apakah string mengandung substring):

javascript
// Polyfill — isi fungsinya
if (!String.prototype.includes) {
  String.prototype.includes = function(cari) {
    // Hint: pakai indexOf
    // ... kode kamu di sini
  };
}

// Test
console.log("Halo Dunia".includes("Dunia")); // true
console.log("Halo Dunia".includes("Mars"));  // false

Rangkuman Bab 2

TopikPoin Utama
DebuggingPakai DevTools + breakpoint untuk masalah kompleks, console.log untuk cek cepat
Coding StyleKonsisten, rapi, pakai linter (ESLint)
KomentarJelaskan "kenapa", bukan "apa". Kode self-descriptive > komentar
Kode NinjaContoh BURUK — nama jelas, satu fungsi satu tugas
TestingTulis test otomatis, satu test satu hal, BDD cycle
Polyfill/TranspilerTranspiler = ubah sintaks, Polyfill = tambah fungsi. Tulis modern, biar tool yang urus

Next: Bab 3 — Object: Dasar-Dasar 🎯

Sudah paham materi ini?

Tandai sebagai selesai untuk melacak progress-mu.