Data mesh membagi data per domain, tetapi menimbulkan pertanyaan penentu: batas domain ditentukan dari mana? Memotong mengikuti struktur tim bisa salah ketika tim direorganisasi; memotong mengikuti sistem yang kebetulan ada bisa mencampur konsep yang berbeda. Domain-driven design (DDD), yang dirintis Eric Evans di dunia rekayasa perangkat lunak, menyediakan kosakata yang teruji untuk masalah ini: bounded context, ubiquitous language, agregat, dan anti-corruption layer. Bab ini menerjemahkan kosakata tersebut ke dunia arsitektur data dan membuktikan manfaatnya lewat simulasi.
Bounded Context dan Bahasa Domain #
Inti DDD adalah pengakuan bahwa satu kata bisa berarti hal berbeda di bagian organisasi yang berbeda. Kata “pesanan” di domain Pesanan berarti keranjang belanja beserta status pembayarannya; di domain Pengiriman, “pesanan” berarti paket fisik dengan alamat dan nomor resi. Bounded context adalah batas validitas sebuah model: di dalam batas tersebut, satu istilah punya satu makna yang disepakati — inilah yang disebut ubiquitous language.
| Istilah DDD | Makna | Padanan arsitektur data |
|---|---|---|
| Bounded Context | batas validitas sebuah model | domain data dengan schema miliknya |
| Agregat | kumpulan objek yang konsisten bersama | tabel atau entity inti domain |
| Ubiquitous Language | kosakata bersama satu tim | nama kolom dan metrik yang konsisten |
| Anti-Corruption Layer | penerjemah antar model | mapping schema di pipeline |
Setiap bounded context menerbitkan datanya sebagai data product — titik di mana DDD bertemu mesh dan fabric dari dua chapter sebelumnya:
Anti-Corruption Layer #
Ketika konteks Analitik memakai data dari konteks Pesanan, Analitik tidak boleh menempel pada schema milik Pesanan. Bila menempel, perubahan kecil di sumber — ganti nama kolom, ubah format — langsung merembet ke semua konsumen. Anti-corruption layer (ACL) memutus rembetan tersebut: sebuah lapisan penerjemah yang dimiliki konsumen, mengubah event sumber menjadi bentuk internal konsumen. Sumber bebas berevolusi; selama ACL diperbarui, konsumen tidak merasakan apa-apa.
Simulasi ACL dengan Python #
Kita simulasikan penerjemahan event antar konteks TokoKita. Domain Pesanan mengirim event dengan schema miliknya; konteks Analitik memiliki peta terjemahan dan atribut internalnya sendiri:
# Event dari domain Pesanan - schema dimiliki domain Pesanan
event_pesanan = {
"order_id": "ORD-0042",
"pelanggan": "budi",
"nilai_idr": 128000,
"terjadi_pada": "2026-01-15T09:12:00+07:00",
"sumber": "app-android",
}
# Konteks Analitik tidak mengenal nama kolom milik domain Pesanan;
# ACL memegang peta terjemahan dan atribut internal milik Analitik.
PETA_KOLOM = {
"order_id": "order_key",
"nilai_idr": "gross_idr",
"terjadi_pada": "event_ts",
}
ID_PELANGGAN = {"budi": "C-1001", "siti": "C-1002", "dewi": "C-1003"}
def terjemahkan(event):
"""ACL: ganti nama kolom, isi customer_id, buang kolom asing."""
hasil = {}
for kolom, nilai in event.items():
if kolom in PETA_KOLOM:
hasil[PETA_KOLOM[kolom]] = nilai
hasil["customer_id"] = ID_PELANGGAN.get(event["pelanggan"], "C-TAKDIKENAL")
hasil["context"] = "analitik"
return {k: hasil[k] for k in sorted(hasil)}Baris pencetakan event masuk dan keluar dipangkas dari tampilan; hasil eksekusi skrip lengkap berikut:
Output yang Dihasilkan:
Event masuk - schema domain Pesanan:
order_id ORD-0042
pelanggan budi
nilai_idr 128000
terjadi_pada 2026-01-15T09:12:00+07:00
sumber app-android
Event keluar - schema konteks Analitik, hasil ACL:
context analitik
customer_id C-1001
event_ts 2026-01-15T09:12:00+07:00
gross_idr 128000
order_key ORD-0042
Kolom 'pelanggan' dan 'sumber' tidak pernah sampai ke Analitik.
Setelah ganti nama kolom di sumber, output Analitik tetap sama: TrueMari kita telaah baris-baris kode di atas:
- Blok pertama, baris 12-16 (
PETA_KOLOM): peta terjemahan dimiliki konteks Analitik, bukan domain Pesanan — konsumen yang menentukan bentuk datanya sendiri. - Blok pertama, baris 17 (
ID_PELANGGAN): registry identitas internal Analitik; nama pengguna dari sumber diterjemahkan menjadicustomer_idyang stabil. - Blok pertama, baris 20-28 (
terjemahkan): hanya kolom yang terdaftar di peta yang diteruskan —pelanggandansumberdibuang, terbukti pada baris output “Kolom ‘pelanggan’ dan ‘sumber’ tidak pernah sampai ke Analitik”. - Baris output terakhir (
True): verifikasi bahwa perubahan di sumber tidak mengubah hasil konsumen — uji ini dijalankan blok kedua berikut.
Perubahan di Sumber Tanpa Guncangan #
Ujian sesungguhnya sebuah ACL adalah ketika sumber berubah. Domain Pesanan mengganti nama kolom order_id menjadi order_ref; ACL cukup menambah satu baris pemetaan:
# Domain Pesanan mengganti nama kolom 'order_id' menjadi 'order_ref';
# ACL diperbarui, konsumen Analitik tidak merasakan apa pun.
event_baru = dict(event_pesanan)
del event_baru["order_id"]
event_baru["order_ref"] = event_pesanan["order_id"]
PETA_KOLOM["order_ref"] = "order_key"
hasil_baru = terjemahkan(event_baru)
print("Setelah ganti nama kolom di sumber, output Analitik tetap sama:",
hasil_baru == hasil_acl)Blok tersebut membangun event versi baru, memperbarui peta pada satu baris (PETA_KOLOM["order_ref"] = "order_key"), lalu memverifikasi hasil terjemahan tetap identik — baris True di akhir output. Tanpa ACL, perubahan nama kolom semacam ini akan memaksa setiap konsumen mengubah query-nya di saat yang sama.
Penjelasan klasik pola ACL dalam rekayasa perangkat lunak ditulis Martin Fowler di bliki AntiCorruptionLayer , sedangkan penerapan data-nya beririsan dengan Schema Registry dan Data Contracts dari section sebelumnya.
Dengan domain, kontrak, dan penerjemah di tempatnya, kita telah menata sisi organisasi dan sisi data. Pertanyaan berikutnya kembali ke mesin: bagaimana batch dan streaming hidup berdampingan di atas fondasi yang sama? Chapter Batch dan Streaming Architecture merangkainya.