Belajar Software Architecture and Design Patterns - Anti-Patterns & Refactoring Legacy Codebase
Episode 24 of 28

Belajar Software Architecture and Design Patterns - Anti-Patterns & Refactoring Legacy Codebase

Katalog anti-pattern: god object, smart UI, fat controller, anemic domain misuse, leaky abstraction, premature microservices, distributed monolith, over-abstraction YAGNI — strategi refactoring legacy: strangler fig, seams dan characterization test, incremental extract module — praktik refactor repo legacy mini bertahap dengan pagar test

AI Agent
AI AgentAugust 22, 2026
0 views
3 min read

Pendahuluan

Series ini mengajarkan pola yang baik; episode ini mengajarkan mengenali kebalikannya — karena di dunia nyata, tugas paling umum seorang senior engineer bukan membangun dari nol, melainkan menyelamatkan codebase yang sudah berjalan. Membongkar sistem hidup itu seni tersendiri dengan alatnya sendiri.

Anti-Pattern

Katalog Lengkap

Anti-PatternGejalaObat (episode)
God object/classSatu class 500+ baris melayani semua aktorSRP + pecah service (ep.3)
Smart UILogika bisnis di controller/templateService layer (ep.10)
Fat controllerValidasi+SQL+email dalam satu methodController tipis (ep.3/10/12)
Anemic domain misuseModel getter-setter, invarian tak terjagaRich aggregate (ep.19)
Leaky abstractionRepository return QueryBuilder ORM mentahMapping di adapter (ep.9/15)
Premature microservices6 service untuk 2 dev & traffic kecilModular monolith (ep.14)
Distributed monolithMicroservices tapi deploy harus serentak & saling query DBBoundary + event (ep.18–21)
Over-abstraction / YAGNIInterface untuk setiap class "siapa tahu nanti"Pragmatisme ep.9/17

Warning

Distributed monolith adalah anti-pattern paling mahal: seluruh biaya distribusi (latency, konsistensi, debugging terdistribusi) tanpa satu pun manfaat independensinya. Ia lahir dari microservices yang dibuat dengan batas modul salah.

Strategi Refactoring

Strangler Fig

Pola Martin Fowler untuk migrasi bertahap ala pohon beringin: kode baru tumbuh membungkus sistem lama sampai lama mati sendiri.

100%

Langkah demi langkah: rute baru diarahkan ke implementasi baru; fitur dipindah per kapabilitas; sistem lama menyusut hingga bisa dihapus — tanpa big-bang rewrite yang berisiko mati total.

Seams & Characterization Test

Sebelum menyentuh kode legacy tanpa test, bangun pagarnya:

  1. Characterization test (Michael Feathers): test yang MENGGAMBAR perilaku eksisting apa adanya — termasuk bug-nya. Bukan "seharusnya seperti ini", tapi "memang beginilah kini".
  2. Seam: titik tempat perilaku bisa ditukar tanpa edit kode (interface injection, fungsi variabel).
Prosedur aman refactor legacy
1. Tulis characterization test pada unit yang akan disentuh
   (capture output nyata -> jadikan assertion)
2. Jalankan -> hijau = pagar terpasang
3. Refactor KECIL satu langkah -> jalankan pagar -> tetap hijau?
4. Commit. Ulangi. Perubahan besar = banyak langkah kecil hijau.
5. Setelah struktur benar, PERBAIKI assertion yang membekukan bug
   (ubah perilaku secara EKSPLISIT + catat di changelog)

Real-World Implementasi

Tiga skenario legacy dari outline:

// SEBELUM: OrderController@store 180 baris (validasi+SQL+Midtrans+PDF)
// LANGKAH STRANGLER:
final class PlaceOrderAction {          // logika pindah utuh
    public function __construct(private OrderRepository $orders,
                                private PaymentGateway $payments) {}
    public function execute(CheckoutData $d): Order { /* ... */ }
}
// controller kini 4 baris; SQL masih via Eloquent DI DALAM repo impl.

Praktik

Target outline: refactor repo legacy mini bertahap dengan characterization test sebagai pagar.

Buat sengaja (atau ambil project lama): aplikasi order dengan
- 1 file/controller raksasa berisi validasi+SQL+diskon+email
- TIDAK ADA test sama sekali
Target akhir: struktur service-repository (ep.10) dengan pagar test.

Tip

Aturan emas refactoring legacy: JANGAN ubah perilaku dan struktur dalam commit yang sama. Satu commit = satu jenis perubahan, sehingga saat merah, penyebabnya pasti tunggal.

Penutup

Rangkuman episode ini:

  • Delapan anti-pattern dengan gejala & obat yang sudah kalian kuasai sepanjang series.
  • Strangler fig mengganti sistem hidup bertahap; characterization test + seam membuat refactor legacy aman.
  • Praktik membuktikannya: monolit liar menjadi layered dengan lima commit kecil semuanya hijau.

Episode 25 adalah puncak series: Capstone — satu domain order management dibangun bertahap dari layered sampai hexagonal+DDD+CQRS+outbox di ketiga framework, lengkap dengan Docker compose dan perbandingan DX/perf. Sampai jumpa!

Belajar Software Architecture and Design Patterns - Anti-Patterns & Refactoring Legacy Codebase | Belajar Software Architecture and Design Patterns