# Teknik Refactoring Kode yang Benar-Benar Mengubah Metrik Tim

URL: https://codebasechat.com/id/journal/teknik-refactoring-kode
Type: blog
Locale: id
Published: 2026-06-29
Updated: 2026-06-30

---

> Panduan teknik refactoring kode yang benar-benar mengubah metrik tim: waktu commit pertama engineer baru, tingkat bug per modul, dan durasi review PR.

Ada modul yang tidak ada yang mau menyentuhnya. Bug menumpuk di sana. Setiap PR yang menyentuhnya butuh dua kali lebih lama untuk direview. Tiga engineer di timmu sudah menyebutnya "lorong berhantu" secara independen. Kamu tahu itu perlu di-refactor, tapi kamu juga tahu bahwa orang terakhir yang mencoba masuk ke sana menghilang selama dua sprint dan keluar dengan feature flag yang rusak dan ekspresi sedikit kalah.

Teknik refactoring kode ada dalam spektrum dari "ganti nama variabel" sampai "restrukturisasi batas layanan secara keseluruhan." Panduan ini membahas yang benar-benar menggerakkan metrik: waktu-ke-commit-pertama untuk engineer baru, tingkat bug per modul, dan durasi review PR.

## Extract Method: Teknik Refactoring yang Bisa Kamu Lakukan Hari Ini

Kalau kamu hanya bisa menjalankan satu teknik pada sebuah codebase, Extract Method adalah pilihannya. Kamu mengidentifikasi blok kode di dalam fungsi panjang yang melakukan satu hal yang koheren, menariknya ke fungsi bernama, dan mendapat dua manfaat langsung: fungsi induk jadi terbaca, dan fungsi yang diekstrak jadi bisa diuji secara terpisah.

Rule of thumb yang sering dipakai: kalau kamu harus menulis komentar untuk menjelaskan apa yang dilakukan sebuah blok kode, blok itu seharusnya menjadi fungsi. Nama fungsi menjadi komentar itu sendiri, dan tidak seperti komentar, nama fungsi memecah build ketika sudah tidak relevan.

Ini bukan preferensi estetika. Ini tentang berapa lama seorang engineer baru butuh waktu untuk melacak bug melalui sebuah fungsi 200 baris dibanding fungsi 20 baris dengan sub-fungsi bernama jelas. Perbedaannya bisa dua jam versus sepuluh menit.

Contoh sederhana yang menggambarkan poinnya:

`# Sebelum: fungsi panjang dengan komentar untuk setiap blok
def process_order(order):
    # Validasi order
    if not order.items:
        raise ValueError("Order kosong")
    if order.total < 0:
        raise ValueError("Total tidak valid")

    # Hitung diskon
    discount = 0
    if order.customer.is_premium:
        discount = order.total * 0.15
    elif order.total > 1000000:
        discount = order.total * 0.10

    # Terapkan pajak
    tax_rate = 0.11  # PPN Indonesia
    final_total = (order.total - discount) * (1 + tax_rate)
    return final_total

# Sesudah: Extract Method membuat setiap bagian bisa diuji
def validate_order(order):
    if not order.items:
        raise ValueError("Order kosong")
    if order.total < 0:
        raise ValueError("Total tidak valid")

def calculate_discount(order):
    if order.customer.is_premium:
        return order.total * 0.15
    elif order.total > 1000000:
        return order.total * 0.10
    return 0

def apply_tax(amount, tax_rate=0.11):
    return amount * (1 + tax_rate)

def process_order(order):
    validate_order(order)
    discount = calculate_discount(order)
    return apply_tax(order.total - discount)`Sekarang `validate_order`, `calculate_discount`, dan `apply_tax` bisa diuji secara independen. Dan ketika aturan diskon berubah, kamu tahu persis di mana mencarinya.

![Dua engineer berkolaborasi dalam sesi code review di standing desk dengan diagram arsitektur di whiteboard](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-06/6cb492-inline1.webp)

## Replace Conditional dengan Polymorphism

Rantai if/elif/else yang panjang atau switch statement yang memeriksa field tipe adalah salah satu pola paling umum yang membuat kode sulit diperluas. Solusinya adalah mengganti conditional dengan hierarki kelas atau strategy pattern. Setiap case menjadi kelasnya sendiri dengan interface yang sama.

Skip teknik ini kalau conditional kamu hanya memiliki dua cabang dan tidak mungkin berkembang. Polymorphism punya overhead: kamu sekarang punya beberapa file di mana sebelumnya hanya ada satu fungsi. ROI-nya baru muncul pada skala tertentu.

Tanda bahwa sudah waktunya: ketika kamu menambah tipe baru dan harus menelusuri lima if/else berbeda di codebase untuk memastikan tidak ada yang terlewat. Itu bukan bug developer, itu bug arsitektur.

Survei Stack Overflow 2024 melaporkan 62% developer merasa frustrasi oleh technical debt. Tapi tidak semua technical debt sama: conditional complexity yang berkembang setiap sprint jauh lebih mahal daripada kode lama yang tidak pernah disentuh.

## Hotspot Analysis: Di Mana Harus Refactor Pertama Kali

Gabungkan cyclomatic complexity dengan frekuensi perubahan. Sebuah modul bisa sangat buruk tapi tidak tersentuh selama tiga tahun. Merefactornya adalah arkeologi, bukan engineering. Modul yang merugikanmu adalah yang berantakan DAN yang timmu masuki setiap minggu.

Caranya praktis:

**Langkah 1:** Jalankan tool complexity untuk mendapat skor cyclomatic per file.

- 
Python: `radon cc src/ -a -s`

- 
JavaScript/TypeScript: `npx complexity-report --format json src/`

- 
Go: `gocyclo -top 20 ./...`

**Langkah 2:** Ambil 20 file dengan change frequency tertinggi dari git:

`git log --format=format: --name-only | \
  sort | uniq -c | sort -rg | head -20`**Langkah 3:** Interseksikan keduanya. File yang muncul di kedua daftar adalah prioritas refactoring-mu. Buat spreadsheet sederhana: skor complexity di satu kolom, jumlah commit di kolom lain, kalikan untuk skor hotspot.

BCG 2024 melaporkan ROI 3x lebih tinggi untuk refactoring sistematis dibanding ad-hoc. McKinsey 2024 melaporkan penyelesaian 40-50% lebih cepat dengan modernisasi sistematis. Perbedaannya ada di sini: mereka yang sistematis memilih berdasarkan data, bukan berdasarkan siapa yang paling keras mengeluh di standup.

![Tangan developer di keyboard dengan kode syntax-highlighted terlihat di layar IDE gelap](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-06/003fd2-inline2.webp)

## Branch-by-Abstraction: Refactoring Sistem yang Sedang Berjalan

Buat abstraksi yang membungkus implementasi saat ini, pindahkan caller untuk menggunakan abstraksi, tulis implementasi baru di baliknya, lalu switch. Ini adalah cara kerja strangler fig pattern di tingkat layanan.

Mengapa ini penting? Karena big bang refactoring hampir selalu gagal. Tim menghabiskan tiga sprint dalam mode refactoring-only, sistem produksi menimbulkan tekanan, dan akhirnya refactoring dibatalkan setengah jalan dengan kode yang lebih buruk dari sebelumnya karena ada dua pola yang bercampur.

Branch-by-Abstraction membuat refactoring bisa dilakukan secara inkremental sambil sistem tetap berjalan. Abstraksinya menjadi titik kontrol: kamu bisa rollback implementasi baru tanpa menyentuh caller.

Urutannya:

- 
Buat interface/abstraksi yang merepresentasikan kontrak yang diinginkan

- 
Buat adapter yang mengimplementasikan interface tersebut menggunakan kode lama

- 
Pindahkan semua caller untuk menggunakan interface, bukan implementasi langsung

- 
Tulis implementasi baru yang juga mengimplementasikan interface

- 
Switch ke implementasi baru secara bertahap (modul per modul, atau fitur flag)

- 
Hapus implementasi lama ketika sudah tidak ada caller

Setiap langkah bisa di-deploy dan diuji secara independen. Tidak ada "freeze" selama refactoring.

## Replace Magic Number dengan Named Constant

Named constant bukan preferensi gaya. Ini adalah mekanisme single-source-of-truth. Ketika constant berubah, ia berubah di mana-mana secara otomatis.

Contoh yang sering muncul di codebase produksi:

`# Sebelum
if response.status_code == 429:
    time.sleep(60)
    if retry_count > 3:
        raise MaxRetriesExceeded()

# Sesudah
RATE_LIMIT_STATUS_CODE = 429
RATE_LIMIT_BACKOFF_SECONDS = 60
MAX_RETRY_ATTEMPTS = 3

if response.status_code == RATE_LIMIT_STATUS_CODE:
    time.sleep(RATE_LIMIT_BACKOFF_SECONDS)
    if retry_count > MAX_RETRY_ATTEMPTS:
        raise MaxRetriesExceeded()`Saat batas rate API berubah dari 60 detik menjadi 30 detik, kamu mengubah satu baris, bukan mencari semua tempat di codebase yang menggunakan angka `60` (yang mungkin juga berarti timeout database, atau batas karakter input, atau hal lain sama sekali).

Tambahkan komentar pada constant yang butuh konteks:

`# PPN Indonesia per Peraturan Menteri Keuangan 2022
VAT_RATE = 0.11

# Limit upload per Cloudflare Workers free tier (bytes)
MAX_UPLOAD_SIZE_BYTES = 100 * 1024 * 1024`Komentar di sini memberikan konteks yang tidak bisa diekspresikan oleh nama variabel saja.

![Rak server dengan kabel berantakan di kiri versus kabel tertata rapi di kanan, metafora visual untuk refactoring kode](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-06/afe5e9-inline3.webp)

## Introduce Parameter Object

Fungsi yang menerima enam argumen adalah fungsi yang akan dipanggil dengan salah. Ketika sekelompok parameter selalu berjalan bersama, mereka termasuk dalam satu objek.

Tanda peringatannya jelas: kalau kamu melihat fungsi yang sama dipanggil di tiga tempat berbeda dan setiap kali kamu harus memeriksa urutan argumennya di dokumentasi, itu tanda bahwa parameter object sudah terlambat diperkenalkan.

`# Sebelum: rawan salah urutan
create_invoice(
    customer_id,
    items,
    discount_percentage,
    tax_rate,
    due_days,
    currency_code
)

# Sesudah: self-documenting, bisa divalidasi
@dataclass
class InvoiceRequest:
    customer_id: str
    items: list[OrderItem]
    discount_percentage: float = 0.0
    tax_rate: float = 0.11
    due_days: int = 30
    currency_code: str = "IDR"

    def validate(self):
        if self.discount_percentage < 0 or self.discount_percentage > 1:
            raise ValueError("Diskon harus antara 0 dan 1")
        if self.due_days < 1:
            raise ValueError("Jatuh tempo minimal 1 hari")

create_invoice(InvoiceRequest(
    customer_id=customer_id,
    items=items,
    discount_percentage=0.15
))`Manfaatnya berlapis: fungsi jadi lebih mudah dibaca, pemanggil tidak perlu ingat urutan argumen, dan objek itu sendiri bisa dijadikan value object dengan validasi built-in.

## Mindset Preparatory Refactoring

Refactor tepat sebelum menambahkan fitur, bukan sebagai proyek tersendiri. Kent Beck merumuskan ini dengan jelas: "jadikan perubahannya mudah, lalu buat perubahan yang mudah itu." Manajemen tidak perlu menyetujui inisiatif refactoring ketika sudah tertanam dalam pekerjaan fitur.

Ini adalah reframing yang penting untuk tim yang bekerja di bawah tekanan delivery. Pertanyaannya bukan "kapan kita punya waktu untuk refactoring?" tapi "refactoring apa yang membuat fitur berikutnya lebih cepat?"

Dalam praktik: sebelum mulai mengimplementasi fitur baru, identifikasi modul yang akan kamu sentuh. Kalau modul itu masuk dalam hotspot analysis, alokasikan 20-30% waktu sprint untuk preparatory refactoring dulu. Waktu itu akan kembali dalam bentuk berkurangnya bug dan review yang lebih cepat.

Cara mempresentasikan ini ke product manager: "Saya perlu 1,5 hari untuk membersihkan modul checkout sebelum menambahkan integrasi GoPay. Tanpa itu, estimasi fiturnya 3 hari, dengan tingkat bug yang lebih tinggi dan review yang lebih lambat. Dengan itu, estimasi jadi 2 hari total, kode yang lebih bersih, dan lebih mudah dimodifikasi untuk integrasi Dana bulan depan." Angka yang konkret membuat percakapan berbeda.

## Apa yang AI Lakukan (dan Tidak Lakukan) untuk Refactoring

Cursor, GitHub Copilot, dan Cody mengurangi friction untuk refactoring mekanis. Mereka bisa membantu Extract Method, rename variabel, dan bahkan menyarankan pola seperti Replace Conditional dengan Polymorphism ketika kamu menunjukkan kodenya.

Tapi mereka tidak memberitahumu di mana harus refactor. Tidak ada dari mereka yang mempertimbangkan tren complexity, tidak ada yang tahu file mana yang paling sering dimodifikasi timmu, dan tidak ada yang memahami konteks bisnis yang membuat modul tertentu lebih kritis dari yang lain.

Lapisan strategis tetap menjadi keputusan manusia. AI membantu eksekusi setelah kamu tahu apa yang harus dilakukan, bukan untuk menentukan apa yang harus dilakukan. Kamu tidak bisa mendelegasikan "di mana kita paling menderita" ke Copilot.

Yang berhasil: gunakan AI untuk Draft extract method saat kamu sudah mengidentifikasi blok yang mau diekstrak. Minta rename suggestion untuk membuat nama lebih ekspresif. Minta generate test untuk fungsi yang baru diekstrak. Itu semua mempercepat eksekusi yang sudah kamu putuskan secara strategis.

## Mulai dari Mana Senin Ini

Jalankan hotspot analysis pada repo-mu minggu ini. Ambil file dengan skor tertinggi. Terapkan Extract Method pada tiga fungsi terpanjang. Tulis test. Commit dengan pesan yang merujuk skor complexity yang kamu mulai dari.

Kamu tidak perlu sprint refactoring khusus. Kamu perlu kebiasaan: sebelum menyentuh modul untuk fitur baru, cek skor hotspot-nya, dan kalau tinggi, luangkan 25 menit untuk Extract Method pada fungsi terburuk di sana. Dalam dua bulan, metrik review PR untuk modul itu akan berubah.

Metrik yang bisa kamu ukur sekarang: rata-rata durasi review PR untuk 10 PR terakhir yang menyentuh modul tersebut. Catat angkanya sebelum mulai. Bandingkan setelah delapan minggu. Kalau tidak berubah, diagnosis hotspot-mu mungkin salah dan perlu diulang.

## FAQ

### Apa itu teknik refactoring kode dan mengapa penting untuk tim engineering?

Teknik refactoring kode adalah metode untuk memperbaiki struktur kode internal tanpa mengubah perilaku eksternalnya. Ini penting karena mengurangi technical debt, mempercepat onboarding engineer baru, dan menurunkan tingkat bug pada modul yang sering disentuh. BCG 2024 melaporkan ROI 3x lebih tinggi untuk refactoring sistematis dibanding ad-hoc.

### Mana teknik refactoring kode yang harus diprioritaskan pertama?

Mulai dengan hotspot analysis untuk mengidentifikasi modul yang paling berantakan DAN paling sering diubah. Kemudian terapkan Extract Method pada fungsi terpanjang di modul tersebut. Ini memberikan ROI tertinggi karena fokus pada kode yang benar-benar memengaruhi produktivitas tim sehari-hari.

### Bagaimana cara melakukan hotspot analysis pada sebuah repo?

Gabungkan dua data: skor cyclomatic complexity per file (gunakan radon untuk Python, complexity-report untuk JS, gocyclo untuk Go) dengan frekuensi perubahan dari git log (`git log --format=format: --name-only | sort | uniq -c | sort -rg | head -20`). File yang muncul di kedua daftar teratas adalah prioritas refactoring-mu.

### Apakah AI seperti Copilot bisa menggantikan keputusan strategis dalam teknik refactoring kode?

Tidak. AI seperti Cursor, GitHub Copilot, dan Cody sangat membantu untuk refactoring mekanis seperti Extract Method atau rename. Tapi mereka tidak tahu di mana harus refactor secara strategis: tidak mempertimbangkan tren complexity, frekuensi perubahan tim, atau konteks bisnis modul.

### Apa itu preparatory refactoring dan bagaimana cara menerapkannya?

Preparatory refactoring adalah refactor yang dilakukan tepat sebelum menambahkan fitur baru, bukan sebagai proyek terpisah. Kent Beck merumuskannya: 'jadikan perubahannya mudah, lalu buat perubahan yang mudah itu.' Dalam praktik: alokasikan 20-30% waktu sprint untuk membersihkan modul yang akan kamu sentuh sebelum menambahkan fitur baru.

### Kapan Replace Conditional dengan Polymorphism tidak worth dilakukan?

Skip teknik ini kalau conditional hanya memiliki dua cabang dan tidak mungkin berkembang. Polymorphism menambahkan overhead berupa beberapa file baru. ROI-nya hanya muncul ketika jumlah case terus bertambah setiap sprint atau ketika setiap case memiliki logic yang cukup kompleks untuk dijustifikasi.

### Bagaimana melakukan refactoring pada sistem yang sedang berjalan di produksi?

Gunakan Branch-by-Abstraction: buat abstraksi yang membungkus implementasi saat ini, pindahkan caller ke abstraksi, tulis implementasi baru di baliknya, lalu switch secara bertahap. Ini memungkinkan refactoring inkremental tanpa menghentikan sistem dan memberikan kemampuan rollback tanpa menyentuh kode caller.