Belajar OOP dengan Java - Clean Code & Refactoring
Series/Belajar OOP/Episode 21
Episode 21 of 23

Belajar OOP dengan Java - Clean Code & Refactoring

Mengasah kualitas kode: prinsip clean code soal penamaan, method kecil dan YAGNI/DRY, mengenali code smells seperti long parameter list dan god class, lalu refactoring dengan extract method dan replace conditional with polymorphism menggunakan tool IntelliJ.

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Selama 20 episode, kita membangun fitur dan desain. Episode ini membalik perspektif: kode yang buruk — seperti apa, mengapa ia muncul, dan bagaimana memperbaikinya secara sistematis. Ini seni clean code dan praktik refactoring, yang dipopulerkan buku Clean Code karya Robert C. Martin dan Refactoring karya Martin Fowler.

Mengapa ini puncak dari OOP? Karena OOP memberi kalian alat desain, tetapi kualitas lahir dari kebiasaan: menamai dengan jujur, memecah method yang panjang, dan — kuncinya — mengubah kode tanpa mengubah perilaku. Kalian akan membaca dan merawat kode puluhan kali lebih sering daripada menulisnya dari nol.

Prinsip Clean Code

Penamaan: Nama yang Jujur

Nama adalah dokumentasi pertama. Kode yang baik dibaca seperti prosa:

JavaAnti-pattern: nama menyesatkan
public void proc() {
    List<String> d = ambilData();
    for (String x : d) {
        if (x.length() > 5) {
            System.out.println(x);
        }
    }
}
JavaNama yang jujur
public void cetakDataPanjang() {
    List<String> data = ambilData();
    for (String item : data) {
        if (item.length() > 5) {
            System.out.println(item);
        }
    }
}

Aturan penamaan:

  • Method = kata kerja: cetakDataPanjang, hitungTotal.
  • Variabel = kata benda yang menjelaskan isi: data, totalPesanan.
  • Class = kata benda domain: Rekening, LayananPesanan.
  • Boolean dimulai dengan is/has: isAktif, hasItem.
  • Hindari singkatan (proc, d, tmp) dan nama generik (data, info, handler).

Biaya nama yang buruk tidak terlihat di menit pertama, tetapi terbayar sebagai waktu baca yang terbuang setiap kali kalian atau orang lain menyentuh kode itu.

Method Kecil: Satu Hal, Satu Tingkat Abstraksi

Method panjang adalah magnet bug — alurnya mustahil diikuti. Pecah sampai setiap method mengerjakan satu hal di satu tingkat abstraksi:

JavaMethod panjang
public void prosesPesanan(Pesanan p) {
    if (p.getStatus().equals("MENUNGGU")) {
        double total = 0;
        for (Item i : p.getItemList()) {
            total += i.getHarga() * i.getQty();
        }
        p.setTotal(total);
        kirimEmail("Pesanan diterima", p.getEmail());
        simpanKeDatabase(p);
    }
}
JavaDipecah menjadi method kecil
public void prosesPesanan(Pesanan p) {
    if (!p.menunggu()) {
        return;
    }
    hitungTotal(p);
    notifikasiDiterima(p);
    simpan(p);
}
 
private void hitungTotal(Pesanan p) {
    p.setTotal(p.getItemList().stream()
            .mapToDouble(i -> i.getHarga() * i.getQty())
            .sum());
}

Bandingkan: prosesPesanan sekarang adalah daftar isi yang terbaca; detail tersembunyi di method kecil. Kode dengan method kecil juga lebih mudah diuji (episode 16) — setiap langkah punya titik test sendiri.

YAGNI dan DRY

Dua prinsip yang sering disalahpahami:

  • YAGNI (You Aren't Gonna Need It) — jangan membangun abstraksi untuk kebutuhan yang belum ada. Fitur khayalan menambah kompleksitas tanpa nilai.
  • DRY (Don't Repeat Yourself) — jangan menyalin logika yang sama. Duplikasi = perbaikan harus dilakukan di banyak tempat, dan sering lupa salah satunya.
JavaAnti-pattern: duplikasi
public double hargaKopi(int qty) { return qty * 25000; }
public double hargaTeh(int qty)  { return qty * 20000; }

Kedua method sebenarnya pola yang sama — abstraksi yang salah tempat vs duplikasi. Yang benar bukan langsung meng-abstraksi ke generik (YAGNI), tetapi menunggu sampai pola ketiga muncul, baru generalisasi dengan keyakinan. Keseimbangannya: DRY mencegah duplikasi bodoh, YAGNI mencegah abstraksi prematur.

Code Smells: Tanda Bahaya

Code smell adalah gejala di kode yang mengisyaratkan desain bermasalah:

Long Parameter List

Method dengan 5+ parameter sulit dipakai dan mudah salah urutan:

JavaAnti-pattern: parameter panjang
public void kirimLaporan(String nama, String email, String alamat,
        String kota, String kodePos, String jenis) {
    // 6 parameter, sulit dibaca & dipanggil
}

Bungkus parameter yang berkaitan menjadi satu object — record (episode 10) sempurna untuk ini:

JavaGrouping parameter
public record Alamat(String jalan, String kota, String kodePos) {}
 
public void kirimLaporan(String nama, String email, Alamat alamat, String jenis) {}

4 parameter pun masih banyak; jika terus bertambah, pertimbangkan parameter object penuh.

God Class

Class yang menangani banyak tanggung jawab (ingat SRP di episode 14):

JavaGod class
public class Aplikasi {
    void login() { }
    void hitungPajak() { }
    void kirimEmail() { }
    void bacaFile() { }
    void cetakLaporan() { }
    void kirimNotifikasi() { }
}

Satu class, enam domain berbeda. Perbaikannya dengan extract class — pindahkan tiap kelompok logika ke class-nya sendiri.

Teknik Refactoring

Refactoring = mengubah struktur tanpa mengubah perilaku. Dua teknik yang paling berdampak:

Extract Method

Memindahkan blok kode ke method baru dengan nama yang menjelaskan — teknik inti yang sudah kita praktikkan di atas:

JavaSebelum extract method
public void cetakFaktur() {
    // 30 baris logika perhitungan di sini...
    // 20 baris logika pencetakan di sini...
}
JavaSetelah extract method
public void cetakFaktur() {
    double total = hitungTotal();
    cetakBaris(total);
}
 
private double hitungTotal() {
    // logika perhitungan
    return 0;
}
 
private void cetakBaris(double total) {
    // logika pencetakan
}

Replace Conditional with Polymorphism

Teknik favorit untuk menghilangkan if/else berantai — kita sudah melihat arahnya di episode 8 dan 14. Inilah versi refactoring-nya:

JavaSebelum: kondisional berantai
public double ongkosKirim(String jenis) {
    if (jenis.equals("motor")) return 5000;
    else if (jenis.equals("mobil")) return 10000;
    else return 0;
}
JavaSesudah: polymorphic dispatch
public interface Kiriman {
    double ongkos();
}
 
public record KirimanMotor() implements Kiriman {
    public double ongkos() { return 5000; }
}
 
public record KirimanMobil() implements Kiriman {
    public double ongkos() { return 10000; }
}

Pemanggil cukup kiriman.ongkos() — tanpa if, terbuka untuk ekstensi (OCP). Ini pola refactoring yang mengubah cabang statis menjadi keputusan dinamis.

Tools Refactoring: IntelliJ IDEA

Kekuatan IntelliJ IDEA (dan VS Code) ada di refactoring terotomasi yang aman — ubah struktur tanpa menyentuh perilaku:

  • Extract Method (Ctrl+Alt+M) — pilih blok, beri nama, IDEA membuat method baru.
  • Rename (Shift+F6) — ganti nama simbol, IDEA memperbarui semua referensi.
  • Introduce Parameter / Variable — otomatiskan variabel sementara.
  • Extract Interface / Class — pecah god class.
  • Inline — kebalikan extract, untuk kode yang terlalu dipecah.

Tip

Kunci refactoring yang aman: test dulu, refactor kemudian (episode 16). Kalian hanya berani mengubah struktur tanpa takut jika ada test yang menjaga perilaku. Bagi tim produksi, refactoring tanpa test adalah judi; dengan test, menjadi rutinitas yang tenang.

Pola Kerja: Boy-Scout Rule

Satu kebiasaan yang mengubah tim: tinggalkan kode lebih bersih dari saat kalian datang (boy-scout rule). Saat menyentuh file, perbaiki satu smell kecil — ganti nama, extract satu method. Kecil per hari, tetapi dalam setahun codebase berubah drastis tanpa perlu proyek refactoring besar yang berisiko.

Warning

Refactoring bukan waktu untuk menambah fitur. Saat sesi refactoring, hanya struktur yang berubah — kalau terlintas ide fitur, catat dan kerjakan nanti di sesi terpisah. Mencampur keduanya membuat perubahan sulit direview dan dibatalkan.

Penutup

Inti yang harus dibawa pulang:

  • Penamaan jujur dan method kecil adalah fondasi keterbacaan.
  • YAGNI mencegah abstraksi prematur; DRY mencegah duplikasi; seimbangkan keduanya.
  • Smell utama: long parameter list, god class, kondisional berantai.
  • Teknik inti: extract method dan replace conditional with polymorphism.
  • Refactoring aman jika ditopang test dan tool (IntelliJ), dan dilakukan terpisah dari perubahan fitur.
  • Terapkan boy-scout rule — bersihkan sedikit demi sedikit.

Di episode 22 — episode terakhir — kita akan membahas ekosistem, alternatif & refleksi akhir: perbandingan Java vs Python vs Kotlin vs C# vs Rust vs Go, kapan memilih bahasa mana, rekap seluruh series, dan checklist produksi lengkap. Sampai jumpa di episode 22!