Belajar Software Architecture and Design Patterns - Clean Architecture & Onion
Episode 16 of 28

Belajar Software Architecture and Design Patterns - Clean Architecture & Onion

Clean Architecture Uncle Bob: Entities, Use Cases, Interface Adapters, Frameworks & Drivers; The Dependency Rule; kemiripan Onion architecture; pragmatisme vs ceremony — struktur src domain application infrastructure presentation di NestJS, cmd internal usecase Fiber, dan folder di luar struktur default Laravel — praktik use case PlaceOrder dengan dependency rule divalidasi architecture test

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

Pendahuluan

Hexagonal (ep.15) menempatkan domain di pusat. Clean Architecture (Robert C. Martin) dan Onion Architecture (Jeffrey Palermo) merumuskan ide yang sama dengan bahasa berbeda — dan menambahkan satu aturan yang membuat semuanya bisa ditegakkan otomatis: The Dependency Rule.

Episode ini menyatukan ketiganya, lalu membahas bagian yang jarang dibahas jujur: kapan ceremony-nya tidak sepadan.

Konsep

Empat Lingkaran Clean Architecture

100%
  • Entities: objek & aturan bisnis paling inti — bertahan walau aplikasi berganti bentuk.
  • Use Cases: orkestrasi alur aplikasi ("saat order dibuat: validasi → charge → simpan → notifikasi").
  • Interface Adapters: konversi antar format (controller/presenter, implementasi repository).
  • Frameworks & Drivers: detail — framework web, database, ORM.

The Dependency Rule

Satu kalimat yang mengikat semua lingkaran: dependensi kode hanya boleh mengarah ke dalam. Lingkaran luar tahu lingkaran dalam; kebalikannya mustahil. Data pun harus dikonversi di batas agar bentuk ORM/HTTP tak bocor masuk.

Onion Architecture menyebut hal serupa (domain core → domain services → application services → outer ring); hexagonal menyebutnya ports & adapters. Ketiganya adalah satu gagasan: proteksi logika bisnis dari detail teknis via arah dependensi.

Perbedaan praktis yang perlu kalian tahu
hexagonal : fokus KONTRAK (ports) - cocok saat banyak sisi I/O
clean     : fokus USE CASE sebagai unit utama - vocabulary kaya utk tim besar
onion     : fokus LAYERING model domain - asal-usul historisnya
Semua membagi aturan yang sama: dependensi menuju inti.

Pragmatisme vs Ceremony

Kejujuran engineering yang wajib: clean architecture punya biaya nyata — file mapper lebih banyak, interface untuk segalanya, boilerplate mapping DTO↔entity↔row. Untuk CRUD sederhana ia overkill (ingat catatan repository ep.9). Nilainya muncul ketika:

  1. Logika bisnis kompleks dan berubah cepat (invarian mahal).
  2. Umur sistem panjang (>2 tahun), tim berganti personel.
  3. Detail teknis benar-benar berpotensi diganti (DB/vendor/framework).

Aturan series ini: pragmatic clean — terapkan penuh pada modul kompleks, layered/modular biasa untuk modul tipis (episode 17 membahas matriks keputusannya).

Real-World Implementasi

// application/place-order.usecase.ts - TIDAK mengenal NestJS:
export class PlaceOrder {
  constructor(
    private orders: OrdersRepoPort,     // interface milik domain
    private pricing: PricingPort,
  ) {}
  async exec(cmd: PlaceOrderCmd): Promise<PlaceOrderResult> {
    const total = await this.pricing.quote(cmd.items);
    if (!total.ok) throw new DomainError(total.reason);
    const order = Order.place(cmd.customerId, cmd.items, total.amount);
    await this.orders.save(order);
    return { orderId: order.id, totalMinor: total.amount.minor };
  }
}

Praktik

Target outline: use case PlaceOrder dengan dependency rule divalidasi lewat architecture test.

// tests/architecture/dependency-rule.test.ts (dependency-cruiser)
forbidden: [
  {
    name: 'domain-imports-nothing-outer',
    from: { path: '^src/domain/' },
    to: { path: '^src/(application|infrastructure|presentation)|(@nestjs|prisma)' },
  },
  {
    name: 'application-no-infrastructure',
    from: { path: '^src/application/' },
    to: { path: '^src/(infrastructure|presentation)' },
  },
];
// Gagal build jika use case mengimpor adapter -> aturan TIDAK bisa dilanggar diam-diam.

Checklist akhir episode:

Checklist ep16
[x] Struktur 4 lingkaran eksplisit di ketiga lab
[x] Use case PlaceOrder murni (nol import framework) - lolos arch test
[x] Mapping data terjadi di batas lingkaran (bukan dump entity)
[x] Arch test masuk CI - dependency rule otomatis
[x] Catatan ADR singkat: modul mana layak clean, mana cukup modular-layered

Note

Jika arch test kalian pertama kali gagal dan menemukan 3–5 pelanggaran nyata — selamat, tool itu sudah membayar dirinya sendiri di hari pertama.

Penutup

Rangkuman episode ini:

  • Clean/Onion = hexagonal yang sama dengan kosakata berbeda; intinya The Dependency Rule menuju entitas.
  • Pragmatisme: penuh untuk modul kompleks, ringan untuk CRUD tipis — ceremony tanpa nilai adalah debt juga.
  • Architecture test mengubah aturan dari dokumen menjadi gerbang CI.

Episode 17 menjawab pertanyaan besar yang tertunda: Layered vs Hexagonal vs Clean — kapan pakai apa? Matriks kompleksitas, studi kasus startup/fintech/enterprise, dan latihan ADR lengkap. Sampai jumpa!

Belajar Software Architecture and Design Patterns - Clean Architecture & Onion | Belajar Software Architecture and Design Patterns