Design Heuristics Dimana Saat Harus Realistis dengan Domain-Driven Design
Jika di pembahasan sebelumnya kita belajar tentang semua elemen keren di DDD — dari bounded context, aggregate, sampai communication patterns, mungkin kini muncul pertanyaan praktis:
“Kapan sih kita benar-benar perlu pakai DDD? Apakah semua bagian sistem harus pakai domain model penuh?”
Jawabannya singkat tapi penting: tidak selalu. Dan di sinilah kita mulai masuk ke inti bab ini: design heuristics — kumpulan prinsip berpikir agar kita tahu seberapa dalam menerapkan DDD, dan kapan harus berhenti sebelum berlebihan.
Heuristik: Bukan Aturan, Tapi Kompas
Kata heuristic berarti “petunjuk praktis untuk membuat keputusan yang baik dalam kondisi tidak pasti.” Dalam konteks DDD, heuristik membantu kita memilih pendekatan desain yang seimbang antara nilai bisnis dan biaya implementasi.
DDD bukan dogma. Ia bukan tentang “semua harus punya domain model lengkap.” Ia adalah cara berpikir agar sistem kita mencerminkan realitas bisnis secukupnya — tidak kurang, tapi juga tidak berlebihan.
“Heuristics are not rules — they are good advice for most situations.” — Vlad Khononov, Learning Domain-Driven Design (2022)
Prinsip Dasar 1: Gunakan Kompleksitas dengan Bijak
DDD diciptakan untuk domain yang kompleks secara bisnis, bukan sekadar teknis. Kalau sistem kamu hanya memindahkan data antar tabel tanpa aturan khusus, maka DDD penuh justru akan memperlambat tim.
Bayangkan sistem sederhana seperti user management, login, atau report generator. Fungsi-fungsi itu bisa selesai dengan cepat pakai pola Transaction Script atau Active Record.
Tapi ketika mulai muncul hal-hal seperti:
“kalau pengguna premium, logika perhitungan komisinya berbeda,”
“status langganan berubah otomatis tergantung perilaku,”
“ada peraturan bisnis yang saling bertabrakan,”
maka itu tanda domain mulai kompleks. Dan di situlah Domain Model menjadi alat yang tepat.
Heuristik #1: Semakin kompleks logika bisnis, semakin layak DDD digunakan.
Prinsip Dasar 2: Model Harus Menghasilkan Nilai Bisnis
Kadang engineer terjebak membangun model yang indah tapi tidak berdampak. DDD tidak mengejar keindahan teknis, tapi kejelasan makna bisnis.
Sebelum membuat entitas, aggregate, atau event, selalu tanyakan:
“Apakah model ini membantu tim memahami atau memecahkan masalah bisnis?”
Kalau jawabannya tidak, mungkin kamu sedang membuat arsitektur demi arsitektur.
Contoh sederhana:
Katakan kita sedang membangun sistem pembelian tiket.
Model yang bermanfaat:
struct Ticket {
id: u64,
status: TicketStatus,
}
enum TicketStatus {
Reserved,
Paid,
Cancelled,
}
Model yang “terlalu DDD tapi tidak berguna”:
struct TicketAggregate {
id: u64,
ticket_entity: TicketEntity,
ticket_state: TicketState,
ticket_repository: Arc<dyn Repository>,
}
Yang satu berbicara tentang tiket dan statusnya, yang lain berbicara tentang framework dan istilah arsitektur. Model yang baik selalu dekat dengan bahasa domain, bukan dengan jargon teknis.
Heuristik #2: Model yang baik berbicara dalam bahasa bisnis, bukan bahasa framework.
Prinsip Dasar 3: Pisahkan Domain yang Penting dari yang Biasa
Tidak semua bagian sistem punya nilai strategis yang sama. Beberapa bagian adalah core domain — di sanalah keunggulan kompetitif bisnis berada. Yang lain hanyalah supporting atau bahkan generic subdomain.
Gunakan tenaga DDD di tempat yang paling berdampak.
Jenis Domain Fokus Pendekatan Core Domain Inovasi, keunggulan kompetitif Domain Model penuh (DDD taktis lengkap) Supporting Domain Mendukung operasi Pola sederhana seperti Active Record Generic Domain Umum untuk semua bisnis Gunakan library atau SaaS
Contoh nyata:
Core Domain: algoritme rekomendasi di e-commerce.
Supporting Domain: sistem pembayaran internal.
Generic Domain: login, autentikasi, logging.
Heuristik #3: Investasikan DDD di tempat yang memberi nilai strategis terbesar.
Prinsip Dasar 4: Jangan Jadikan DDD Sebagai Target, Tapi Sebagai Alat
Engineer yang baru mengenal DDD sering terlalu semangat: semua hal dibuat Aggregate, semua entitas punya Repository, semua event dicatat.
Padahal DDD bukan checklist, melainkan toolbox. Gunakan hanya alat yang relevan untuk masalah di depan mata.
Heuristik #4: DDD bukan tujuan akhir, melainkan sarana untuk memahami dan menyelesaikan kompleksitas.
Ciri bahwa kamu terlalu jauh: model makin abstrak, tapi semua orang di tim justru makin bingung. Ciri bahwa kamu tepat: model membantu tim berdebat tentang bisnis, bukan tentang kode.
Prinsip Dasar 5: Evolve, Don’t Freeze
Model domain bukan kontrak permanen. Ia seharusnya tumbuh bersama pemahaman bisnis.
Ketika aturan bisnis berubah, biarkan model ikut berevolusi. Jangan terjebak pada rasa takut “merusak arsitektur yang sudah rapi.”
Heuristik #5: Model yang hidup lebih berguna daripada model yang sempurna.
Misalnya, awalnya kamu hanya punya dua status pembayaran: Pending
dan Paid
. Lalu muncul kebutuhan “Refunded”. Tambahkan saja, meskipun awalnya belum semua proses mendukung.
enum PaymentStatus {
Pending,
Paid,
Refunded,
}
Model berkembang, pengetahuan bertambah — persis seperti bisnisnya.
Prinsip Dasar 6: Biarkan Bounded Context Mengatur Diri Sendiri
Ketika sistem tumbuh besar, mudah tergoda membuat “model universal” yang bisa dipakai semua tim. Padahal itu berbahaya.
Model yang terlalu umum akan kehilangan makna di setiap konteks. Lebih baik setiap bounded context punya modelnya sendiri — walau istilahnya sama tapi maknanya berbeda.
Contoh nyata:
Di Sales Context, “Customer” berarti orang yang membeli produk.
Di Support Context, “Customer” berarti orang yang sedang punya tiket bantuan aktif.
Keduanya sah. Yang penting, mereka tidak saling memaksakan makna.
Heuristik #6: Hargai otonomi bounded context — lebih baik model ganda yang jelas daripada model tunggal yang membingungkan.
Prinsip Dasar 7: Arsitektur Ada untuk Melayani Domain
Jangan biarkan framework atau pola arsitektur membatasi desain domain. Ingat bahwa model domain adalah pusat dari sistem, bukan lapisan di bawah framework.
Kalau framework ORM memaksa semua entitas harus punya id
integer, padahal di domain kamu lebih masuk akal pakai code
sebagai identitas, maka ubahlah framework, bukan domainnya.
struct Product {
code: String, // Bukan ID auto-increment
name: String,
}
Heuristik #7: Framework boleh diganti, domain tidak.
Prinsip Dasar 8: Ubiquitous Language Adalah Tes Terbaik
Kalau kamu ingin tahu seberapa sehat model domainmu, lihat bagaimana tim berbicara tentang bisnisnya.
Kalau engineer, PM, dan ahli domain bisa bicara tentang “Order”, “Refund”, dan “Shipment” tanpa kebingungan — artinya modelmu sudah bekerja. Kalau tiap meeting diwarnai “maksud kamu order yang di database atau order yang di API?”, artinya modelmu butuh perbaikan.
Heuristik #8: Jika bahasa di kode dan di percakapan bisnis sama, kamu sedang menerapkan DDD dengan benar.
Ringkasnya, Pragmatism is the Real DDD
DDD bukan sekadar teori elegan untuk sistem besar. Ia adalah cara berpikir untuk memastikan bahwa software yang kita bangun selalu berbicara tentang bisnis, bukan sekadar data.
Namun, setiap engineer yang matang tahu:
Tidak semua sistem butuh domain model penuh,
Tidak semua konteks perlu aggregate,
Dan tidak semua tim siap hidup dengan kompleksitas DDD sejak hari pertama.
Gunakan heuristics sebagai kompas, bukan peta mutlak. Tugas kita bukan membuat DDD sempurna, tapi membuat sistem yang bermakna, terpelihara, dan berumur panjang.
“The goal of DDD is not to apply all its patterns, but to use the right ones, in the right context, for the right reasons.” — Vlad Khononov, Learning Domain-Driven Design (2022)
Referensi
Khononov, V. (2022). Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy. O’Reilly Media.