Managing Technical Debt — Clean Code

Technical debt adalah konsekuensi dari menulis kode yang cepat tapi tidak optimal — seperti utang finansial, makin lama dibiarkan, makin besar "bunganya"…

Technical debt (utang teknis) adalah jalan pintas di kode yang menghemat waktu sekarang, tapi bikin tiap perubahan berikutnya lebih mahal sampai jalan pintas itu dibereskan. Bayangin beli HP pakai paylater. HP-nya kamu pegang hari ini, tapi selama utangnya belum lunas, tiap bulan ada bunga. Di kode, "HP hari ini" adalah fitur yang rilis tepat waktu, dan "bunga" adalah menit tambahan yang kamu bayar setiap kali menyentuh kode itu.

🧪 Tebakan cepat: utang TD-01 di kasir Raka butuh 60 menit untuk dilunasi, dan selama belum lunas, tiap perubahan voucher makan 20 menit ekstra. Setelah berapa kali perubahan voucher, melunasinya sudah balik modal: 1, 3, atau 10? Tebak dulu, jawabannya ada di bagian "Bunga dihitung, bukan dirasakan".

Jalan pintas waktu Harbolnas

Seminggu sebelum Harbolnas, Raka minta struk dan email konfirmasi menampilkan berapa yang dihemat pembeli. Biar keburu, potongannya dihitung ulang di dua tempat baru, gak lewat tabel VOUCHERS dari lesson Refactoring Techniques:

const VOUCHERS = { HEMAT10: 0.1 };

function applyVoucher(amount, voucherCode) {       // tempat 1
  return amount - amount * (VOUCHERS[voucherCode] ?? 0);
}
// TD-01: disalin waktu Harbolnas, ada di daftar utang
function savingLine(subtotal, voucherCode) {       // tempat 2
  const rate = voucherCode === 'HEMAT10' ? 0.1 : 0;
  return 'Hemat: ' + formatRupiah(subtotal * rate);
}
function emailLine(email, subtotal, voucherCode) { // tempat 3
  const rate = voucherCode === 'HEMAT10' ? 0.1 : 0;
  return email + ': kamu hemat ' + formatRupiah(subtotal * rate);
}

Fiturnya rilis tepat waktu dan keempat keranjang tetap OK. Itu untungnya berutang. Tapi tarif voucher sekarang tertulis di tiga tempat.

Lalu PR #14 dari lesson Code Review menambah HEMAT20 ke VOUCHERS saja. Keranjang A dengan HEMAT20:

OK   Total: Rp 211.000
BEDA Hemat: Rp 0, harusnya Hemat: Rp 49.000
BEDA [email protected]: kamu hemat Rp 0, harusnya [email protected]: kamu hemat Rp 49.000

Totalnya benar, tapi struk dan email bilang pembeli gak hemat apa-apa. Itulah bunganya: tiap perubahan voucher harus ingat tiga tempat, bukan satu.

Pokok dan bunga

Istilah ini dari Ward Cunningham, di laporan pengalamannya tentang sistem WyCash (konferensi OOPSLA, 1992): mengirim kode yang belum pas itu seperti berutang, dan "tiap menit yang dihabiskan untuk kode yang belum pas dihitung sebagai bunga utang itu". Jadi utang punya dua angka:

Bunga cuma dibayar saat kodenya disentuh. Kode jelek yang gak pernah diubah gak berbunga.

Bunga dihitung, bukan dirasakan

Total menit untuk sejumlah perubahan voucher ke depan:

Perubahan voucher Biarkan (30 per perubahan) Lunasi dulu (60 + 10 per perubahan)
1 30 70
2 60 80
3 90 90
4 120 100
6 180 120

Impas di perubahan ketiga, dan mulai yang keempat, melunasi lebih murah. Itu jawaban tebakannya: 3. Rumusnya pokok dibagi bunga, 60 ÷ 20 = 3. Voucher kasir Raka berubah kira-kira dua kali sebulan (perkiraan tim), jadi dalam dua bulan sudah balik modal. Angka seperti ini yang kamu bawa ke Raka, bukan "kodenya jelek".

Daftar utang (debt register)

Utang yang gak dicatat gak pernah dibayar, karena gak ada yang ingat. Daftar utang kasir Raka:

ID Utang Bunga Pokok Keputusan
TD-01 Tarif voucher di 3 tempat +20 menit tiap perubahan voucher, kira-kira 2 kali sebulan 60 menit Lunasi sekarang
TD-02 Gak ada keranjang tepat Rp 200.000 di test <= yang salah lolos tiap aturan ongkir diubah 5 menit Bayar sambil lewat
TD-03 hitung(k, v) lama di skrip laporan tahunan 0, gak pernah diubah 90 menit Biarkan, tetap dicatat

Yang bukan utang: bug (hasilnya salah, perbaiki sekarang) dan fitur yang belum dibuat (itu backlog).

Sengaja atau gak sadar

Martin Fowler (artikel "Technical Debt Quadrant", 2009) membagi utang dengan dua pertanyaan: sadar atau gak waktu berutang (deliberate atau inadvertent), dan hati-hati atau ceroboh (prudent atau reckless).

Utang yang sengaja lebih gampang dikelola, karena bisa langsung dicatat saat itu juga.

Bayar sambil lewat: Boy Scout Rule

Robert C. Martin di buku Clean Code (2008) memakai aturan pramuka: tinggalkan perkemahan lebih bersih daripada saat kamu datang. Untuk kode: tiap kali menyentuh sebuah bagian, rapikan sedikit. TD-02 dilunasi begini: lain kali kamu mengubah addShipping, tambahkan satu baris test.

const cartE = [{ name: 'Topi Raka', price: 40000, qty: 5 }]; // tepat Rp 200.000
check(calculateTotal(cartE, ''), 'Total: Rp 200.000');

Lima menit, dibayar saat kamu memang sudah di sana. Utang besar seperti TD-01 tetap butuh waktu khusus yang dijadwalkan.

Latihan: assessDebt

Selain daftar yang ditulis manusia, alat bisa mengukur gejala utang: persentase kode duplikat, cyclomatic complexity (jumlah jalur yang bisa dilewati sebuah fungsi; tiap if, loop, && atau || menambah satu), test coverage (persentase kode yang dijalankan test), dan jumlah paket yang ketinggalan versi (npm outdated). Latihan memberi skor dengan ambang di bawah ini. Ambangnya khusus latihan; tiap tim menyepakati ambangnya sendiri.

Ukuran Kena kalau Poin Saran
duplicateLines > 20 25 Kurangi duplikasi kode
cyclomaticComplexity > 10 20 Sederhanakan fungsi kompleks
testCoverage < 60 30 Tingkatkan test coverage
outdatedDependencies > 5 25 Perbarui dependensi yang outdated

Tiap ukuran yang kena menambah poinnya ke debtScore (misalnya debtScore += 25) dan menambah sarannya ke recommendations dengan push, urut seperti tabel. Ambangnya ketat: tepat 20, 10, 60 atau 5 belum kena, jadi { 20, 10, 60, 5 } menghasilkan skor 0 dan low. Cuma coverage yang kena di { 5, 3, 50, 1 }: skor 30, medium, satu saran. Contoh di editor, { 25, 12, 45, 8 }, kena semua:

{"debtScore":100,"priority":"critical","recommendations":["Kurangi duplikasi kode","Sederhanakan fungsi kompleks","Tingkatkan test coverage","Perbarui dependensi yang outdated"]}

⚠️ Jebakan yang sering ketemu

TL;DR: Technical debt adalah jalan pintas yang menghemat waktu sekarang dan menagih bunga tiap kali kodenya disentuh (metafora Ward Cunningham, 1992). Hitung dua angkanya: pokok (biaya melunasi) dan bunga (menit ekstra per perubahan). Tarif voucher yang disalin ke tiga tempat bikin HEMAT20 tampil Hemat: Rp 0 di struk dan email, dan tiap perubahan voucher makan 20 menit ekstra; pokok 60 menit impas setelah 3 perubahan. Catat tiap utang di daftar utang dengan ID, bunga, pokok dan keputusan; kode jelek yang gak pernah diubah bunganya nol, biarkan. Deliberate berarti sadar ambil jalan pintas, inadvertent berarti gak sadar karena belum tahu caranya. Boy Scout Rule: tinggalkan kode sedikit lebih baik dari saat kamu menemukannya. Di latihan, tiap ukuran yang melewati ambang (> 20, > 10, < 60, > 5) menambah 25, 20, 30, 25 poin dan satu saran; 80 ke atas critical, 60 high, 30 medium, di bawahnya low.

Yang akan kamu pelajari