Bab 2: Kualitas Kode
"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
F12atauCtrl + 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.
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:
function hitungDiskon(harga, persen) {
let potongan = harga * persen / 100;
debugger; // browser akan berhenti di sini
let hargaAkhir = harga - potongan;
return hargaAkhir;
}⚠️
debuggercuma aktif kalau DevTools terbuka. Kalau ditutup, diabaikan.
Tombol Navigasi Debugging
| Tombol | Fungsi | Hotkey |
|---|---|---|
| ▶ Resume | Lanjut sampai breakpoint berikutnya | F8 |
| ⤵ Step | Jalankan 1 baris, masuk ke dalam fungsi | F9 |
| ⤴ Step Over | Jalankan 1 baris, SKIP isi fungsi | F10 |
| ⬆ Step Out | Keluar dari fungsi saat ini | Shift+F11 |
console.log — Debugging Sederhana
Kalau males buka DevTools, cara paling gampang:
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
- Jangan hapus
console.logsatu-satu — pakaiCtrl+Hreplace semua - Pakai
console.table()untuk lihat array/object dalam bentuk tabel console.error()danconsole.warn()buat bedain jenis pesan
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.
function cekUmur(umur) {
debugger;
if (umur < 12) {
return "anak";
} else if (umur < 18) {
return "remaja";
} else {
return "dewasa";
}
}
cekUmur(15); // coba ganti-ganti nilainya2.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"
// ✅ 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
// ✅ 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, bukana=b+c
3. Panjang Baris — Maksimal 80-120 Karakter
Kalau terlalu panjang, pecah:
// ❌ 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
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
// ❌ 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)
// ✅ 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 Guide | Dipakai Oleh |
|---|---|
| Airbnb | Banyak startup |
| StandardJS | Tanpa 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
# Install
npm install -g eslint
# Jalankan
eslint namaFile.jsESLint 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.
Perbaiki kode berikut sesuai aturan coding style yang benar:
// 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"
// 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"
// 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
// ❌ 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
- Arsitektur keseluruhan — gambaran besar sistem
- Dokumentasi fungsi (JSDoc) — parameter, return value
- Keputusan yang tidak obvious — "kenapa pakai cara ini, bukan cara itu"
- Hack/workaround — "ini workaround untuk bug di library X"
JSDoc — Dokumentasi Formal
/**
* 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
Lihat kode ini. Hapus komentar yang tidak perlu, dan tambahkan komentar yang berguna:
// 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
// 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
// BURUK
let brsr = navigator.userAgent;
let lst = document.querySelectorAll("li");
// BAIK
let browserInfo = navigator.userAgent;
let listItems = document.querySelectorAll("li");❌ Nama Terlalu Abstrak
// 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
// 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
// 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
| Prinsip | Artinya |
|---|---|
| Nama deskriptif | Variabel/fungsi harus jelas tujuannya dari namanya |
| Satu fungsi, satu tugas | Jangan campur validasi + tampilan + logging |
| Jangan reuse variabel | Bikin variabel baru, bukan timpa yang lama |
| Hindari singkatan | Kecuali yang sudah universal (i, j untuk loop) |
Refactor kode "ninja" ini jadi kode yang bersih:
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
- Kamu fix bug A → tanpa sadar, fitur B jadi rusak
- Kamu takut ubah kode lama → kode jadi "museum" yang nggak ada yang berani sentuh
- 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
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:
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
| Tool | Fungsi |
|---|---|
| Mocha | Framework test — menyediakan describe, it |
| Chai | Library assertion — menyediakan assert.equal, dll |
| Sinon | Spy/mock — untuk test lanjutan |
Prinsip: Satu Test, Satu Hal
// ❌ 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
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
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() { ... });
});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).
// 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.
// 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:
- Kamu tulis kode modern
- Babel baca kode kamu
- Babel tulis ulang pakai sintaks lama
- 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:
// 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
| Transpiler | Polyfill | |
|---|---|---|
| Menangani | Sintaks baru (??, ?., arrow function) | Fungsi baru (Array.includes, Promise) |
| Cara kerja | Tulis ulang kode | Tambah implementasi fungsi |
| Kapan jalan | Sebelum deploy (build time) | Saat kode dijalankan (runtime) |
| Contoh tool | Babel | core-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
- Selalu tulis kode modern — biar transpiler yang urus kompatibilitas
- Cek support fitur di caniuse.com
- Chrome biasanya paling update — cocok buat development
Tulis polyfill sederhana untuk fungsi String.prototype.includes (cek apakah string mengandung substring):
// 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")); // falseRangkuman Bab 2
| Topik | Poin Utama |
|---|---|
| Debugging | Pakai DevTools + breakpoint untuk masalah kompleks, console.log untuk cek cepat |
| Coding Style | Konsisten, rapi, pakai linter (ESLint) |
| Komentar | Jelaskan "kenapa", bukan "apa". Kode self-descriptive > komentar |
| Kode Ninja | Contoh BURUK — nama jelas, satu fungsi satu tugas |
| Testing | Tulis test otomatis, satu test satu hal, BDD cycle |
| Polyfill/Transpiler | Transpiler = 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.