Mengatasi Kompleksitas Domain dengan Bounded Contexts
Setelah memiliki bahasa yang sama, dengan Ubiquitous language, kita menyadari bahwa dalam satu perusahaan bisa jadi ada beberapa model untuk hal yang sama. Ahli domain dari divisi berbeda mungkin punya definisi berbeda terhadap suatu konsep.
Contohnya dari buku Khononov (2022): perusahaan telemarketing; tim marketing memandang “lead” sebagai sekadar notifikasi ketika seorang prospek menunjukkan minat. Tapi tim sales melihat “lead” sebagai proses penjualan yang lengkap, dari awal sampai konversi – sebuah entitas yang jauh lebih kompleks.
Masalahnya, jika kita mencoba membuat satu model tunggal yang menampung dua pandangan berbeda ini, model itu bakal terlalu besar dan kompleks, atau malah terlalu disederhanakan sehingga tidak memenuhi kebutuhan salah satu tim. Prefix seperti “marketingLead” dan “salesLead” tidak membantu banyak karena tetap membingungkan pemakai bahasa (orang cenderung tidak pakai istilah seperti itu dalam obrolan sehari-hari).
Solusi DDD-nya adalah Bounded Context: kita memecah bahasa umum tadi menjadi beberapa bahasa yang lebih kecil, masing-masing dipakai dalam konteks tertentu.
Secara harfiah, “bounded context” berarti “konteks yang memiliki batas.”
Kata bounded artinya “dibatasi,” dan context artinya “lingkungan makna” atau “tempat di mana istilah-istilah punya arti tertentu.”
Dalam konteks DDD, Bounded Context adalah batas eksplisit di mana satu model domain dan bahasa umum (ubiquitous language) berlaku secara konsisten.
Di dalam batas itu, istilah, aturan, dan logika bisnis punya arti yang jelas dan tidak membingungkan. Tapi di luar batas itu, istilah yang sama bisa berarti lain, dan itu tidak apa-apa.
Dalam contoh tadi, kita bisa punya dua bounded context: Marketing dan Sales. Di tiap konteks ini, istilah “Lead” hanya punya satu arti saja sesuai kebutuhan konteks itu. Dengan cara ini, tidak ada kebingungan di dalam kode – misalnya marketing::Lead bisa kita definisikan terpisah dari sales::Lead dalam kode Rust:
mod marketing {
#[derive(Debug)]
struct Lead {
contact_info: String,
// ...
}
}
mod sales {
#[derive(Debug)]
struct Lead {
customer_id: u32,
// ...
}
}
Dengan model seperti di atas, marketing::Lead dan sales::Lead mengandung arti berbeda meski namanya sama. Ini menggambarkan bounded context: setiap modul atau bagian sistem memiliki bahasanya sendiri yang konsisten di dalam konteksnya. Lalu, kapan kita berhenti memecah konteks? Sama seperti peta, tiap model punya batas manfaatnya. Bounded context adalah batas pemakaiannya: setiap model hanya berguna dalam domain masalah yang spesifik. Peta jalan tidak bisa dipakai di laut; begitupun model “Lead” marketing tidak berguna untuk logika sales.
DDD mengajarkan bahwa kejelasan makna lebih penting daripada keseragaman istilah.
Dengan bounded context:
Tim bisa bekerja secara independen,
Model mereka tetap konsisten di dalam konteksnya,
Dan integrasi antar konteks bisa diatur lewat pola yang eksplisit (seperti Shared Kernel atau Anticorruption Layer), yang akan dibahas selanjutnya.
Menentukan ukuran bounded context adalah keputusan desain strategis. Semakin luas batasannya, semakin sulit menjaga konsistensi model. Kadang berbagi konteks besar lebih mudah karena integrasi lebih sederhana, tapi terkadang kita perlu memecahnya lagi (misalnya tim terpisah, atau performa terpisah). Aturan umumnya: jika sekumpulan use case (kasus penggunaan) berhubungan erat dengan data yang sama, biarkan saja dalam satu bounded context. Jangan memecah fitur yang koheren menjadi beberapa konteks tanpa alasan kuat, karena setiap kali fungsionalitas berubah, semua konteks yang terpisah harus diubah bersamaan – bikin repot!
Perbedaan subdomain (yang dibahas di artikel memahami domain bisnis) dengan bounded context penting disini. Subdomain berasal dari analisis bisnis (sesuai strategi perusahaan), sedangkan bounded context kita rancang untuk software. Sebagai engineer, kita bebas menentukan batasan model kita. Kadang kita menyelaraskan: satu subdomain inti bisa jadi satu bounded context. Kadang tidak: kita bisa memiliki beberapa model (bound context) untuk satu subdomain untuk tujuan yang berbeda. Misalnya, subdomain akuntansi bisa punya konteks terpisah untuk laporan finansial dan satu lagi untuk perhitungan pajak, dengan model yang berbeda untuk masing-masing.
Selain sebagai batas konsep, bounded context juga menjadi batas fisik dan kepemilikan dalam pengembangan. Secara fisik, tiap bounded context idealnya diimplementasikan sebagai layanan atau modul terpisah sehingga bisa dipilih teknologi yang cocok, dan diedarkan sendiri. Secara tim, satu bounded context hanya diurus satu tim saja; tidak boleh dua tim bekerja di kode yang sama. Ini mencegah asumsi tersembunyi antar tim. Dengan bounded context, kita memetakan struktur organisasi dan arsitektur sistem dalam satu alat yang sama.
Referensi
Khononov, V. (2022). Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy. O’Reilly Media.


