Apa itu Domain-Driven Design (DDD)
DDD itu pendekatan untuk mendesain software yang menempatkan bisnis (domain), bukan teknologi, sebagai pusat pengambilan keputusan teknis.
Tujuannya: bikin sistem yang secara konseptual nyambung dengan masalah bisnis sehingga lebih gampang dipelihara, dikembangkan, dan selaras dengan strategi perusahaan (Khononov, 2022).
Kenapa ada DDD?
Banyak proyek gagal bukan karena bahasa pemrograman, tapi karena salah paham antara orang bisnis dan engineer. DDD menawarkan serangkaian prinsip dan pola (strategic + tactical) untuk:
Mendapatkan & menahan pengetahuan domain (apa istilahnya, apa aturan bisnisnya),
Membagi sistem menjadi bagian-bagian yang masuk akal menurut bisnis,
Menjaga model bisnis tetap bersih di kode (agar tidak jadi big ball of mud).
Singkatnya: kalau kamu capek melihat fitur terus rusak gara-gara asumsi bisnis yang salah, DDD membantu mengurangi itu.
Konsep inti yang mesti dipahami
Ubiquitous Language: bahasa bersama antara engineer & domain expert, semua orang ngomong pakai istilah bisnis yang sama, dan itu tercermin di dokumentasi, tes, dan kode. Tanpa ini, informasi gampang terdistorsi.
Subdomain (core / generic / supporting): analisa bisnis untuk tahu mana bagian yang memberikan keunggulan kompetitif (core), mana yang bisa dibeli/diadopsi (generic), dan mana yang sederhana/pendukung (supporting). Keputusan engineering (build vs buy, investasi tim) bergantung pada penempatan ini.
Bounded Context: batas konsistensi model dan bahasa. Satu istilah boleh punya arti berbeda di konteks berbeda, sehingga kita memecah model agar tiap konteks tetap konsisten dan jelas.
Pattern Integrasi (context mapping): cara-cara konteks saling terhubung, misalnya Shared Kernel, Anticorruption Layer, Conformist, Partnership, Separate Ways, pilih sesuai biaya koordinasi vs duplikasi.
Kelebihan DDD dibanding pendekatan sejenis
Vs. Desain CRUD / “database-first” CRUD-first sering mengarahkan kita membuat model menurut tabel, bukan bisnis. DDD memaksa kita pikir dari istilah & aturan bisnis → model → implementasi. Hasilnya: logika bisnis tersimpan di tempat yang tepat, bukan tercecer di UI/trigger SQL.
Vs. Layered Architecture (tradisional) Layered bagus untuk struktur, tapi tidak menjawab: apa batas domain? DDD menambahkan dimensi strategis (subdomain + bounded context) sehingga arsitektur berhubungan langsung dengan strategi bisnis, bukan hanya pemisahan teknis.
Vs. Clean Architecture / Hexagonal / Ports & Adapters Pola-pola arsitektural ini fokus pada pemisahan concerns dan ketergantungan, sangat kompatibel dengan DDD. Bedanya: DDD memberikan what to model (domain) dan where to place boundaries (bounded contexts), sedangkan Clean Arch memberi blueprint bagaimana memisahkan interface/infrastruktur. Gabungan keduanya kuat: DDD + Hexagonal = domain yang jelas + boundary teknis yang bersih.
Vs. Microservices-first Mikroservis tanpa konsep domain sering berakhir sebagai “silo teknologi” dan tight-coupled lewat API yang buruk. DDD membantu menentukan layanan yang tepat (bounded contexts ↔ layanan) sehingga pembagian mikroservisnya bermakna dari sisi bisnis, bukan hanya dari sisi tim atau fitur.
Vs. Model-Driven / Codegen MDA (model-driven) kadang mengandalkan transformasi otomatis tanpa cukup diskusi dengan domain expert. DDD menekankan co-creation pengetahuan domain dengan ahli bisnis, model harus mencerminkan pemikiran mereka, bukan sekadar artefak mesin.
Intinya: DDD unggul ketika masalahnya kompleks (aturan banyak, istilah samar, perubahan bisnis cepat). Untuk aplikasi sederhana (landing page, form CRUD trivial), DDD sering berlebihan.
Kapan tidak perlu pakai DDD?
Proyek sangat kecil atau PoC dengan lifespan pendek.
Sistem yang 100% bersifat infrastruktur/generic (mis. integrasi billing standar), lebih murah pakai produk siap pakai.
Tim tidak bisa/akan berkomitmen untuk kolaborasi intens dengan domain expert, DDD butuh interaksi terus-menerus.
Contoh kecil (ilustrasi ubiquitous language → kode Rust)
Bayangkan domain bisnis kita punya konsep Order
(dengan arti bisnis jelas). Di DDD, nama ini dipakai di semua level: dokumen, tests, dan kode.
// contoh ilustratif, bukan implementasi lengkap
struct OrderId(u64);
struct Order {
id: OrderId,
customer_id: u64,
items: Vec<OrderItem>,
status: OrderStatus, // misal: Pending, Confirmed, Shipped
}
// method bisnis (encapsulate invariants)
impl Order {
fn confirm(&mut self) -> Result<(), &'static str> {
if self.items.is_empty() { Err("order has no items") } else {
self.status = OrderStatus::Confirmed;
Ok(())
}
}
}
Gunakan nama-nama ini juga dalam diskusi produk: ketika domain expert bilang “konfirmasi pesanan”, semua pihak paham tepat apa yang dimaksud, tidak lagi perlu komentar teknis yang rancu.
Referensi
Khononov, V. (2022). Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy. O’Reilly Media.