<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[-1]]></title><description><![CDATA[-1 looks at education, technology, and programming through one simple question: what changes when one piece is missing? Issues vary: sometimes I preview research, sometimes I write practical how-tos, and sometimes I share a loose idea or code snippet.]]></description><link>https://www.0-1.my.id</link><image><url>https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png</url><title>-1</title><link>https://www.0-1.my.id</link></image><generator>Substack</generator><lastBuildDate>Tue, 14 Apr 2026 16:01:19 GMT</lastBuildDate><atom:link href="https://www.0-1.my.id/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[oon arfiandwi]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[oon@oo.or.id]]></webMaster><itunes:owner><itunes:email><![CDATA[oon@oo.or.id]]></itunes:email><itunes:name><![CDATA[oon arfiandwi]]></itunes:name></itunes:owner><itunes:author><![CDATA[oon arfiandwi]]></itunes:author><googleplay:owner><![CDATA[oon@oo.or.id]]></googleplay:owner><googleplay:email><![CDATA[oon@oo.or.id]]></googleplay:email><googleplay:author><![CDATA[oon arfiandwi]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[mini-redis client & server]]></title><description><![CDATA[Belajar tokio dengan contoh kasus mini-redis.]]></description><link>https://www.0-1.my.id/p/mini-redis-client-and-server</link><guid isPermaLink="false">https://www.0-1.my.id/p/mini-redis-client-and-server</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Tue, 28 Oct 2025 16:58:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Belajar tokio dengan contoh kasus mini-redis.</p><p></p><p><a href="https://tokio.rs/tokio/tutorial/setup">https://tokio.rs/tokio/tutorial/setup</a></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Membedah Dynamo: Resep Rahasia Amazon untuk Sistem yang "Tidak Bisa Mati"]]></title><description><![CDATA[Pernahkah Anda terbangun tengah malam karena notifikasi PagerDuty yang memekakkan telinga?]]></description><link>https://www.0-1.my.id/p/membedah-dynamo-resep-rahasia-amazon</link><guid isPermaLink="false">https://www.0-1.my.id/p/membedah-dynamo-resep-rahasia-amazon</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Mon, 27 Oct 2025 16:55:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Pernahkah Anda terbangun tengah malam karena notifikasi PagerDuty yang memekakkan telinga? Server down, database tidak merespons, dan entah bagaimana, semua jari menunjuk ke arah Anda. Membangun sistem yang tangguh itu sulit. Membangun sistem yang harus selalu online 100%,nbahkan saat separuh dunia digital sedang terbakar, rasanya hampir mustahil.</p>]]></content:encoded></item><item><title><![CDATA[Eksplorasi Dynomite dari Netflix]]></title><description><![CDATA[Proyek open-source Dynomite dari Netflix https://github.com/Netflix/dynomite punya unique selling point karena seperti fitur yang hanya dimiliki oleh redis yang berbayar.]]></description><link>https://www.0-1.my.id/p/eksplorasi-dynomite-dari-netflix</link><guid isPermaLink="false">https://www.0-1.my.id/p/eksplorasi-dynomite-dari-netflix</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sun, 26 Oct 2025 16:59:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Proyek open-source Dynomite dari Netflix <a href="https://github.com/Netflix/dynomite">https://github.com/Netflix/dynomite</a> punya unique selling point karena seperti fitur yang hanya dimiliki oleh redis yang berbayar.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Data Mesh,  Momen Ketika DDD Bertemu Dunia Data]]></title><description><![CDATA[Selama bertahun-tahun, sistem perangkat lunak dan sistem data berkembang dalam dua dunia yang hampir terpisah.]]></description><link>https://www.0-1.my.id/p/data-mesh-momen-ketika-ddd-bertemu</link><guid isPermaLink="false">https://www.0-1.my.id/p/data-mesh-momen-ketika-ddd-bertemu</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sat, 25 Oct 2025 16:57:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Selama bertahun-tahun, sistem perangkat lunak dan sistem data berkembang dalam dua dunia yang hampir terpisah.</p><p>Aplikasi bisnis dibangun dengan prinsip domain dan bounded context, sementara sistem data &#8212; terutama data lake dan data warehouse &#8212; dikelola secara terpusat oleh tim analitik.</p><p></p><p>to be continued.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Event-Driven Architecture, Menyatukan Domain melalui Peristiwa ]]></title><description><![CDATA[Dalam sistem modern, banyak hal tidak lagi berjalan secara berurutan.]]></description><link>https://www.0-1.my.id/p/event-driven-architecture-menyatukan</link><guid isPermaLink="false">https://www.0-1.my.id/p/event-driven-architecture-menyatukan</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Fri, 24 Oct 2025 15:59:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Dalam sistem modern, banyak hal tidak lagi berjalan secara berurutan.</p><p>Perangkat lunak perlu bereaksi terhadap berbagai kejadian yang muncul di waktu berbeda, dari berbagai sumber, dan kadang tanpa koordinasi langsung.</p><p>Inilah konteks di mana Event-Driven Architecture (EDA) menjadi relevan.</p><p></p><p>Sementara Domain-Driven Design (DDD) fokus pada memahami dan memodelkan domain bisnis,</p><p>Event-Driven Architecture fokus pada mengalirkan informasi tentang perubahan domain ke seluruh sistem.</p><p></p><p>to be continued.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Microservices, Antara Ukuran Kecil dan Kompleksitas Besar]]></title><description><![CDATA[Beberapa tahun terakhir, kata microservices seolah menjadi mantra sakti di dunia teknologi.]]></description><link>https://www.0-1.my.id/p/microservices-antara-ukuran-kecil</link><guid isPermaLink="false">https://www.0-1.my.id/p/microservices-antara-ukuran-kecil</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Thu, 23 Oct 2025 16:59:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Beberapa tahun terakhir, kata <em>microservices</em> seolah menjadi mantra sakti di dunia teknologi. Banyak perusahaan beralih dari monolit ke microservices dengan harapan semua masalah skala, performa, dan kolaborasi akan terselesaikan.</p><p>Namun, kenyataannya sering jauh dari harapan: setelah dipecah menjadi banyak service, tim justru kebingungan mengelola dependensi, data tersebar, dan komunikasi antar sistem menjadi mimpi buruk.</p><p>Vlad Khononov menyebut fenomena ini dengan sangat tepat:</p><blockquote><p>&#8220;Microservices are not the destination &#8212; they are the outcome of understanding your domain.&#8221; &#8212; <em>Vlad Khononov, Learning Domain-Driven Design</em> (2022)</p></blockquote><p>Dengan kata lain, <strong>microservices bukan tujuan, melainkan konsekuensi logis dari penerapan DDD yang baik.</strong></p><h2>Microservices dan Janji Kemerdekaan</h2><p>Secara konsep, <em>microservice architecture</em> adalah tentang memecah sistem besar menjadi unit-unit kecil yang <strong>dapat dikembangkan, dirilis, dan diskalakan secara independen.</strong></p><p>Setiap microservice:</p><ul><li><p>Menangani satu fungsi bisnis tertentu,</p></li><li><p>Memiliki data sendiri,</p></li><li><p>Dan bisa dikelola oleh satu tim otonom.</p></li></ul><p>Tujuannya terdengar sederhana: <em>independence and scalability.</em> Namun dalam praktiknya, banyak organisasi gagal karena <strong>tidak memahami batas domain sebelum membagi service.</strong></p><blockquote><p>&#8220;Without understanding domain boundaries, splitting a monolith creates distributed chaos, not distributed systems.&#8221; &#8212; <em>Khononov, 2022</em></p></blockquote><p>Dan di situlah peran DDD menjadi sangat penting.</p><h2>Hubungan DDD dan Microservices</h2><p>DDD memberi fondasi berpikir yang kuat untuk menentukan <strong>batas alami</strong> dari setiap microservice, yaitu melalui konsep <strong>bounded context</strong>.</p><ul><li><p>DDD Concept: Bounded Context</p><ul><li><p>Padanan Microservices: Microservice Boundary </p></li><li><p>Tujuan: Memisahkan logikadan model bisnis secara mandiri </p></li></ul></li><li><p>DDD Concept: <em>Ubiquitous Language</em> </p><ul><li><p>Padanan Microservices: Service API Contract</p></li><li><p>Tujuan: Bahasa dan istilah konsisten dalam satu tim</p></li></ul></li><li><p>DDD Concept: <em>Context Map</em></p><ul><li><p>Padanan Microservices: Service Interaction Diagram</p></li><li><p>Tujuan: Hubungan antar service dan pola komunikasinya</p></li></ul></li><li><p>DDD Concept: <em>Communication Pattern</em> </p><ul><li><p>Padanan Microservices: API/Event Integration</p></li><li><p>Tujuan: Cara service berkoordinasi tanpa coupling</p></li></ul></li></ul><p>Jadi, <em>bounded context</em> dalam DDD bukan sekadar konsep abstrak, ia adalah <strong>peta alami yang membantu kita menentukan microservice yang sehat.</strong></p><h2>Bounded Context Sebagai Panduan Desain Microservice</h2><p>Banyak kegagalan microservice berasal dari salah memotong sistem: dibagi berdasarkan <strong>lapisan teknis</strong> (UI, backend, database), bukan <strong>area bisnis.</strong></p><p>Hasilnya: service terlalu kecil, saling bergantung, dan kehilangan makna bisnis.</p><p>DDD membantu memotong sistem secara <strong>semantik</strong>, bukan <strong>struktural.</strong></p><p><strong>Contoh:</strong> Daripada membagi berdasarkan teknologi:</p><pre><code>/user-api
/payment-service
/database-service</code></pre><p>DDD akan mendorong pembagian berdasarkan domain:</p><pre><code>/billing-context
/inventory-context
/customer-context</code></pre><p>Setiap context punya logika, data, dan bahasa sendiri, itulah microservice yang benar-benar &#8220;domain-driven&#8221;.</p><h2>Integrasi Antar Microservice: Komunikasi Antara Context</h2><p>Ketika kita punya banyak bounded context (atau microservice), komunikasi di antaranya harus dikelola dengan hati-hati.</p><p>DDD memperkenalkan <em>communication patterns</em> yang juga relevan di dunia microservices, seperti:</p><ul><li><p><strong>Customer&#8211;Supplier</strong></p></li><li><p><strong>Conformist</strong></p></li><li><p><strong>Partnership</strong></p></li><li><p><strong>Separate Ways</strong></p></li></ul><p>Dalam konteks arsitektur terdistribusi, pola-pola ini bisa diterjemahkan sebagai:</p><ul><li><p>Customer&#8211;Supplier &#8594; satu service tergantung API dari service lain,</p></li><li><p>Conformist &#8594; mengikuti format upstream tanpa perubahan,</p></li><li><p>Partnership &#8594; dua tim berkolaborasi erat,</p></li><li><p>Separate Ways &#8594; berjalan mandiri tanpa integrasi real-time.</p></li></ul><p>Misalnya:</p><pre><code>// Contoh komunikasi event-driven antar microservice
#[derive(serde::Serialize, serde::Deserialize)]
struct OrderPlaced {
    order_id: u64,
    total: f64,
}

fn publish_order_placed(order: OrderPlaced) {
    // publish ke message broker (Kafka, NATS, dll)
    println!("Publishing event: {:?}", order);
}</code></pre><p>Pendekatan event-driven ini menjaga agar microservice tetap otonom, karena setiap service bereaksi terhadap event, bukan memanggil service lain secara langsung.</p><h2>Tantangan Microservice di Dunia Nyata</h2><p>Meski konsepnya indah, arsitektur microservices membawa <strong>kompleksitas baru.</strong></p><p>Khononov mengingatkan, bahwa:</p><blockquote><p>&#8220;Microservices move complexity from code to communication.&#8221; &#8212; <em>Vlad Khononov, 2022</em></p></blockquote><p>Mari lihat beberapa jebakan umum yang sering terjadi:</p><h3>1. <strong>Over-segmentation (Service Terlalu Kecil)</strong></h3><p>Engineer terlalu semangat memecah sistem hingga setiap fungsi menjadi satu service. Akibatnya, integrasi menjadi rumit dan deployment berantakan.</p><p><em>Solusi:</em> Pastikan setiap service punya makna domain utuh (bounded context lengkap), bukan sekadar endpoint CRUD.</p><h3>2. <strong>Shared Database</strong></h3><p>Beberapa service masih berbagi database yang sama, ini menghapus batas konteks.</p><p><em>Solusi:</em> Setiap service memiliki <strong>database sendiri</strong>, bahkan jika data yang disimpan mirip. Gunakan event untuk sinkronisasi, bukan query silang.</p><h3>3. <strong>Communication Hell</strong></h3><p>Service saling memanggil API secara berantai (A &#8594; B &#8594; C &#8594; D). Jika satu mati, semuanya ikut gagal.</p><p><em>Solusi:</em> Gunakan <strong>asynchronous messaging (event-driven)</strong> untuk mengurangi coupling antar service.</p><h3>4. <strong>Terlalu Banyak Infrastruktur</strong></h3><p>Microservice memerlukan CI/CD pipeline, monitoring, logging, service mesh, dan sebagainya. Untuk tim kecil, overhead ini bisa lebih mahal daripada manfaatnya.</p><p><em>Solusi:</em> Mulai dari <em>modular monolith</em>, struktur monolit yang sudah terpisah per context. Jika sudah stabil, baru evolusikan ke microservice sejati.</p><h2>Modular Monolith Sebagai Titik Awal</h2><p>Khononov menyarankan pendekatan yang realistis:</p><blockquote><p>&#8220;Start with a modular monolith. Split it when you must, not when you can.&#8221; &#8212; <em>Khononov, 2022</em></p></blockquote><p>Artinya, kamu bisa mulai dengan sistem monolit tunggal, tapi struktur internalnya sudah mengikuti prinsip <em>bounded context.</em></p><p>Contoh struktur folder dalam Rust:</p><pre><code>src/
 &#9500;&#9472;&#9472; billing/
 &#9474;    &#9500;&#9472;&#9472; domain.rs
 &#9474;    &#9500;&#9472;&#9472; service.rs
 &#9474;    &#9492;&#9472;&#9472; repository.rs
 &#9500;&#9472;&#9472; inventory/
 &#9474;    &#9500;&#9472;&#9472; domain.rs
 &#9474;    &#9492;&#9472;&#9472; service.rs
 &#9492;&#9472;&#9472; main.rs</code></pre><p>Ketika skala sistem tumbuh, tiap folder domain ini bisa dengan mudah dipecah menjadi microservice independen, karena sejak awal, batas context-nya sudah jelas.</p><h2>DDD sebagai Landasan Microservice Sehat</h2><p>Inti dari pesan Khononov sangat sederhana tapi krusial:</p><blockquote><p>&#8220;Without DDD, microservices are just distributed monoliths.&#8221; &#8212; <em>Vlad Khononov (2022)</em></p></blockquote><p>DDD membantu kita:</p><ol><li><p>Menentukan batas yang sehat (<em>bounded contexts</em>),</p></li><li><p>Menjaga otonomi antar tim,</p></li><li><p>Mencegah duplikasi logika bisnis,</p></li><li><p>Menghindari coupling antar service.</p></li></ol><p>Dengan kata lain, <strong>DDD adalah kompas yang menunjukkan di mana memotong sistem.</strong> Microservices hanyalah hasil fisik dari pemotongan itu.</p><h2>Ringkasnya, Microservices yang Bermakna</h2><p>Microservices bukan soal ukuran kecil, tapi soal <strong>batas makna yang jelas.</strong> Sebuah microservice seharusnya mencerminkan satu domain bisnis yang utuh, bukan sekadar satu tabel di database atau satu endpoint di API gateway.</p><p>DDD membantu kita menemukan batas itu, bukan lewat intuisi arsitek, tapi lewat percakapan lintas tim, pemahaman domain, dan bahasa umum yang disepakati.</p><blockquote><p>&#8220;Good microservices emerge from good domain models.&#8221; &#8212; <em>Vlad Khononov, Learning Domain-Driven Design</em> (2022)</p></blockquote><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[DDD di Dunia Nyata, Antara Ideal dan Kenyataan]]></title><description><![CDATA[Setelah memahami konsep DDD dari sisi teori, strategi, dan taktik, sering kali muncul satu kesimpulan sederhana dari engineer yang sudah mencoba menerapkannya: &#8220;DDD di buku itu indah.]]></description><link>https://www.0-1.my.id/p/ddd-di-dunia-nyata-antara-ideal-dan</link><guid isPermaLink="false">https://www.0-1.my.id/p/ddd-di-dunia-nyata-antara-ideal-dan</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Wed, 22 Oct 2025 16:11:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setelah memahami konsep DDD dari sisi teori, strategi, dan taktik, sering kali muncul satu kesimpulan sederhana dari engineer yang sudah mencoba menerapkannya: &#8220;DDD di buku itu indah. Tapi di dunia nyata&#8230; ya, tidak sesempurna itu.&#8221;</p><p>Dan memang benar. Vlad Khononov sendiri menekankan sejak awal bahwa <em>Domain-Driven Design</em> bukanlah metode magis yang menjamin keberhasilan proyek, melainkan <strong>sekumpulan pola pikir dan alat bantu untuk memahami serta mengelola kompleksitas.</strong></p><p>Dalam bab ini, kita akan melihat <strong>bagaimana DDD diterapkan secara pragmatis di dunia nyata</strong>, termasuk kesalahpahaman umum, jebakan organisasi, dan strategi agar tetap waras dalam menghadapi kenyataan.</p><h2>Kenyataan #1: Tidak Semua Sistem Butuh DDD</h2><p>Salah satu kesalahan paling sering ditemui di dunia profesional adalah <strong>menerapkan DDD di semua tempat.</strong></p><p>Padahal, tidak semua sistem punya kompleksitas yang layak untuk itu.</p><p>DDD diciptakan untuk domain yang:</p><ul><li><p>Kompleks secara <em>bisnis</em>, bukan hanya teknis.</p></li><li><p>Penuh ambiguitas dan aturan yang berubah cepat.</p></li><li><p>Memerlukan komunikasi intens antara developer dan domain expert.</p></li></ul><p>Kalau sistem kamu hanya mencatat data CRUD (Create, Read, Update, Delete), maka memakai DDD lengkap akan terasa seperti <strong>menggunakan bazooka untuk memecahkan telur.</strong></p><blockquote><p>&#8220;DDD is not for every project &#8212; it&#8217;s for the ones where business complexity rules.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><p>Jadi, <em>if it&#8217;s simple, keep it simple.</em> Gunakan pendekatan ringan seperti <em>Transaction Script</em> atau <em>Active Record</em> untuk modul sederhana, dan hanya terapkan DDD penuh pada bagian yang benar-benar strategis.</p><h2>Kenyataan #2: Organisasi Lebih Sulit dari Kode</h2><p>DDD sering kali gagal bukan karena engineer tidak paham model, tapi karena <strong>organisasi tidak siap untuk cara berpikir kolaboratif.</strong></p><p>Di dunia nyata:</p><ul><li><p>Tim terpisah oleh silo,</p></li><li><p>Komunikasi antar departemen buruk,</p></li><li><p>&#8220;Ahli domain&#8221; tidak selalu punya waktu untuk berdiskusi,</p></li><li><p>Dan setiap tim punya KPI sendiri-sendiri.</p></li></ul><p>Hasilnya? Setiap orang punya versi modelnya sendiri, dan <em>ubiquitous language</em> yang ideal di buku berubah jadi <em>babel language</em> di kantor.</p><blockquote><p>&#8220;The real challenge of DDD is not modeling the software &#8212; it&#8217;s modeling the organization.&#8221; &#8212; <em>Khononov, 2022</em></p></blockquote><p><strong>Strategi realistis:</strong> Mulai dari lingkar kecil, satu tim yang mau berkolaborasi penuh. Bangun <em>bounded context</em> pertama di situ, dan buktikan hasilnya. Setelah berhasil, baru tularkan ke tim lain.</p><h2>Kenyataan #3: Bounded Context Itu Tidak Harus Rapi</h2><p>Di teori, <em>bounded context</em> terlihat jelas: setiap domain punya batas logis, bahasa sendiri, dan modelnya tidak tumpang-tindih.</p><p>Tapi di dunia nyata, batas itu sering kabur:</p><ul><li><p>Ada konteks yang saling tumpang tindih,</p></li><li><p>Ada istilah yang &#8220;nyasar&#8221; karena kebutuhan API,</p></li><li><p>Kadang satu tim harus mengurusi dua domain karena alasan praktis.</p></li></ul><p>Dan itu <strong>tidak apa-apa.</strong></p><p>DDD bukan tentang kesempurnaan arsitektur, tapi tentang <em>kesadaran terhadap batasan.</em> Selama tim sadar di mana batas tanggung jawabnya, DDD tetap hidup.</p><blockquote><p>&#8220;It&#8217;s okay if your boundaries are blurry &#8212; as long as you know they&#8217;re blurry.&#8221; &#8212; <em>Khononov, 2022</em></p></blockquote><p>Contohnya, dua tim mungkin sama-sama menggunakan istilah <em>Order</em>. Tapi yang penting adalah:</p><ul><li><p>Mereka tahu makna &#8220;Order&#8221; di masing-masing context,</p></li><li><p>Dan mereka tidak saling memaksakan model satu sama lain.</p></li></ul><h2>Kenyataan #4: Model Akan Selalu Berubah</h2><p>Sering kali, tim DDD pemula ingin membuat <em>domain model final</em> sebelum mulai coding. Padahal, seperti dibahas di Bab 11, <strong>model domain itu hasil belajar, bukan hasil perencanaan.</strong></p><p>Model yang baik bukan yang paling stabil, tapi yang paling mudah beradaptasi.</p><p><strong>Praktik nyata:</strong> Gunakan pendekatan <em>event-driven</em> untuk memantau perubahan domain. Setiap kali muncul <em>event</em> baru yang tidak masuk akal, itu tanda modelmu butuh revisi.</p><p>Misalnya:</p><pre><code>// Model awal
enum OrderStatus {
    Pending,
    Paid,
}

// Setelah bisnis menambah fitur refund
enum OrderStatus {
    Pending,
    Paid,
    Refunded,
}</code></pre><p>Model berkembang bukan karena salah di awal, tapi karena <strong>bisnis berubah dan pengetahuan bertambah.</strong></p><h2>Kenyataan #5: Kompromi Itu Wajar</h2><p>Setiap proyek di dunia nyata berhadapan dengan tiga tekanan utama:</p><ol><li><p><strong>Waktu</strong>: deadline yang ketat,</p></li><li><p><strong>Sumber daya</strong>: tim kecil, beban besar,</p></li><li><p><strong>Teknologi warisan (legacy)</strong>: keputusan lama yang sulit diubah.</p></li></ol><p>Dan di tengah tekanan itu, idealisme DDD kadang harus dikompromikan.</p><blockquote><p>&#8220;A pragmatic architect knows when to bend the rules.&#8221; &#8212; <em>Khononov, 2022</em></p></blockquote><p>Kompromi tidak berarti menyerah. Yang penting adalah tahu <strong>kapan dan kenapa</strong> melanggar prinsip.</p><p> <strong>Contoh kompromi sehat:</strong></p><ul><li><p>Sementara gunakan model anemik (tanpa logika bisnis di entitas), lalu perlahan refactor ketika domain makin jelas.</p></li><li><p>Tulis <em>event</em> secara manual dulu tanpa bus, lalu evolusikan jadi <em>event-driven architecture</em> saat skalanya cukup besar.</p></li><li><p>Gunakan <em>shared database</em> sementara untuk sinkronisasi antar context, tapi tandai sebagai <em>temporary coupling.</em></p></li></ul><p>Kunci keberhasilan DDD di dunia nyata adalah <strong>transparansi dalam kompromi.</strong></p><h2>Kenyataan #6: DDD Adalah Perjalanan, Bukan Tujuan</h2><p>Banyak tim berpikir bahwa &#8220;menerapkan DDD&#8221; adalah milestone yang bisa dicapai. Padahal, DDD itu bukan proyek &#8212; ia <em>cara berpikir yang berkelanjutan.</em></p><p>DDD yang sehat terlihat bukan dari diagram yang indah, tapi dari <strong>komunikasi yang lancar antar tim, pemahaman yang jelas tentang domain, dan model yang tumbuh bersama bisnis.</strong></p><blockquote><p>&#8220;The success of DDD is not measured in aggregates, but in shared understanding.&#8221; &#8212; Vlad Khononov (2022)</p></blockquote><p>Ketika orang bisnis, developer, dan QA bisa berbicara tanpa translator, itulah saat DDD benar-benar hidup, bahkan tanpa disebut DDD.</p><h2>Kenyataan #7: Legacy Systems Bisa Diperbaiki Bertahap</h2><p>Banyak perusahaan tidak memulai dari nol. Mereka punya sistem lama, penuh logika bercampur, dan database yang menua.</p><p>Kabar baiknya: <strong>DDD bisa diterapkan secara bertahap.</strong></p><p>Mulailah dari memetakan domain dan event dengan <em>EventStorming</em> (Bab 12). Temukan <em>bounded context</em> tersembunyi di dalam monolit, dan pisahkan secara evolusioner.</p><p>Contohnya, dari monolit besar, ekstrak satu domain kecil seperti <em>Invoice Management</em> menjadi microservice mandiri dengan domain model sendiri.</p><p>Dengan cara itu, DDD menjadi strategi <em>perbaikan berkelanjutan</em>, bukan proyek overhaul besar.</p><h2>Heuristik untuk Bertahan di Dunia Nyata</h2><p>Khononov menutup buku ini dengan beberapa heuristik penting bagi praktisi DDD:</p><ul><li><p>Heuristik: <strong>Mulai dari percakapan, bukan kode.</strong> </p><ul><li><p>Penjelasan: DDD lahir dari dialog dengan domain expert. </p></li></ul></li><li><p>Heuristik: <strong>Desain secukupnya.</strong> </p><ul><li><p>Penjelasan: Tidak semua bagian butuh arsitektur kompleks. </p></li></ul></li><li><p><strong>Refactor berdasarkan pembelajaran.</strong> </p><ul><li><p>Penjelasan: Evolusi model harus mengikuti realitas bisnis. </p></li></ul></li><li><p><strong>Gunakan bahasa bisnis di kode.</strong> </p><ul><li><p>Penjelasan: Nama-nama class, function, dan event harus masuk akal bagi non-engineer. </p></li></ul></li><li><p><strong>Toleransi terhadap kekacauan.</strong> </p><ul><li><p>Penjelasan: Di awal, model pasti berantakan &#8212; dan itu normal. </p></li></ul></li><li><p><strong>Rayakan perbaikan kecil.</strong> </p><ul><li><p>Penjelasan: Setiap domain yang jadi lebih mudah dipahami adalah kemenangan.</p></li></ul></li></ul><h2>Ringkasnya, DDD yang Sejati Adalah DDD yang Hidup</h2><p>Pada akhirnya, DDD bukan tentang pola, agregat, atau bounded context yang sempurna. DDD adalah tentang <strong>membawa makna bisnis ke dalam perangkat lunak</strong> dengan cara yang bisa berkembang bersama waktu.</p><p>Di dunia nyata, DDD yang berhasil bukan yang 100% sesuai buku, tapi yang 100% <em>dipahami</em> oleh orang-orang yang membangunnya.</p><blockquote><p>&#8220;Perfect DDD doesn&#8217;t exist &#8212; but meaningful DDD does.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[EventStorming dimana Menemukan Pemahaman Bersama Melalui Peristiwa]]></title><description><![CDATA[Salah satu tantangan terbesar dalam DDD bukanlah menulis kode,]]></description><link>https://www.0-1.my.id/p/eventstorming-dimana-menemukan-pemahaman</link><guid isPermaLink="false">https://www.0-1.my.id/p/eventstorming-dimana-menemukan-pemahaman</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Tue, 21 Oct 2025 16:17:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Salah satu tantangan terbesar dalam DDD bukanlah menulis kode,</p><p>melainkan menyatukan pemahaman antara orang-orang yang berbicara bahasa berbeda:</p><p>engineer, product manager, domain expert, dan stakeholder bisnis.</p><p>Setiap orang membawa perspektifnya sendiri:</p><ul><li><p>Engineer berpikir dalam entitas dan API,</p></li><li><p>Product manager berpikir dalam fitur,</p></li><li><p>Domain expert berpikir dalam proses dan peraturan bisnis.</p></li></ul><p>Dan sering kali, perbedaan bahasa ini membuat diskusi berputar tanpa hasil.</p><p>Nah, <em>EventStorming</em> hadir untuk menjembatani semua itu.<br>Ini bukan teknik coding, tapi teknik <strong>berpikir dan berkolaborasi visual</strong> agar tim memahami domain dengan cara yang sama.</p><blockquote><p>&#8220;EventStorming is a workshop-based method to explore complex domains by focusing on domain events.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2>Apa Itu EventStorming?</h2><p>Secara sederhana, <em>EventStorming</em> adalah <strong>cara memetakan alur bisnis dengan menulis peristiwa-peristiwa (event) yang terjadi di domain</strong>, biasanya di atas dinding atau papan besar dengan sticky notes berwarna.</p><p>Kata &#8220;Storming&#8221; di sini menggambarkan proses eksplorasi yang intens dan cepat, bukan diskusi formal yang kaku.<br>Tujuannya bukan langsung &#8220;mendesain arsitektur,&#8221; tapi <strong>mendapatkan pemahaman utuh tentang bagaimana domain bekerja</strong> dari perspektif semua pihak.</p><p><strong>Kata kuncinya:</strong><br>Semua orang bisa berkontribusi, semua ide valid, dan peristiwa (event) adalah bahasa pemersatu.</p><h2>Kenapa EventStorming Penting dalam DDD</h2><p>DDD berfokus pada pemahaman domain.<br>Tapi sering kali, pengetahuan domain tidak tertulis dengan rapi,<br>ia tersebar di kepala orang-orang, dokumen lama, atau asumsi tim.</p><p>EventStorming membantu:</p><ol><li><p><strong>Menyatukan semua stakeholder</strong> di satu ruangan (atau papan digital).</p></li><li><p><strong>Menyingkap logika bisnis tersembunyi</strong> lewat diskusi natural.</p></li><li><p><strong>Membentuk bahasa umum (ubiquitous language)</strong> dari kejadian nyata di domain.</p></li><li><p><strong>Menemukan batas-batas alami (bounded contexts)</strong> berdasarkan pola peristiwa.</p></li></ol><p>Dengan kata lain, EventStorming adalah <strong>cara tercepat untuk &#8220;menemukan domain model&#8221; sebelum menulis satu baris kode pun.</strong></p><h2>Prinsip Utama: Berpikir dalam &#8220;Event&#8221;</h2><p>Daripada bertanya &#8220;entitas apa yang kita butuhkan?&#8221;, facilitator EventStorming akan memulai dengan pertanyaan sederhana: &#8220;Apa saja yang terjadi di domain ini?&#8221;</p><p>Setiap jawaban ditulis dalam format <em>Domain Event</em>, sesuatu yang <em>terjadi</em> di masa lalu dan <em>relevan</em> bagi bisnis.</p><p>Contohnya:</p><ul><li><p><code>OrderPlaced</code></p></li><li><p><code>PaymentReceived</code></p></li><li><p><code>ShipmentSent</code></p></li><li><p><code>CustomerRegistered</code></p></li></ul><p>Setiap event ditempel di dinding dari kiri ke kanan, menggambarkan urutan waktu.</p><p>Dari situ, perlahan terbentuk narasi: bagaimana proses bisnis berjalan, siapa yang terlibat, dan di mana kompleksitas muncul.</p><h2>Warna dan Artefak Utama</h2><p>EventStorming biasanya menggunakan <strong>sticky note dengan warna berbeda</strong>, yang masing-masing mewakili artefak penting dalam domain.</p><ul><li><p>Oranye: Artefak Domain Event</p><ul><li><p>Artinya: Sesuatu yang terjadi di masa lalu</p></li></ul></li><li><p>Biru: Artefak Command</p><ul><li><p>Artinya: Tindakan yang menyebabkan Event</p></li></ul></li><li><p>Kuning: Artefak External System / Policy </p><ul><li><p>Artinya: Sistem atau aturan luar yang memicu tindakan </p></li></ul></li><li><p>Merah muda: Artefak Actor / User</p><ul><li><p>Artinya: Siapa yang menjalankan command</p></li></ul></li><li><p>Hijau: Artefak View / Read Model</p><ul><li><p>Artinya: Informasi yang dilihat pengguna </p></li></ul></li><li><p>Ungu: Artefak Aggregate / Entity</p><ul><li><p>Artinya: Unit logika bisnis yang menangani command</p></li></ul></li></ul><p>Tidak semua workshop butuh semua warna. Fokusnya bukan estetika, tapi pemahaman bersama tentang hubungan sebab-akibat di domain.</p><h2>Fase-Fase EventStorming</h2><p>Menurut Khononov (2022), proses EventStorming umumnya terdiri dari beberapa tahap yang semakin mendalam.</p><h3>1. <strong>Big Picture EventStorming</strong></h3><p>Tujuannya: menemukan <strong>alur bisnis secara keseluruhan</strong>.</p><p>Peserta dari berbagai fungsi (bisnis, teknis, operasional) diminta menuliskan semua <em>event penting</em> dalam proses.<br>Hasilnya sering kali berantakan &#8212; dan itu bagus! Karena di sanalah percakapan penting muncul.</p><p>Contoh:<br>Ketika seseorang menulis <em>PaymentFailed</em>, peserta lain mungkin bertanya,<br>&#8220;Lho, itu terjadi sebelum atau sesudah <em>OrderCancelled</em>?&#8221;<br>Diskusi seperti itu mengungkap <em>aturan bisnis implisit</em> yang selama ini tidak pernah terdokumentasi.</p><h3>2. <strong>Process-Level EventStorming</strong></h3><p>Setelah gambaran besar terbentuk, tim bisa memperdalam satu proses spesifik, misalnya <em>Order Fulfillment</em>.<br>Di tahap ini, kita mulai melihat <em>command</em>, <em>actor</em>, dan <em>aggregate</em> yang terlibat.</p><p>Misalnya:</p><ul><li><p>Command: <code>PlaceOrder</code></p></li><li><p>Aggregate: <code>Order</code></p></li><li><p>Event: <code>OrderPlaced</code></p></li><li><p>Actor: <code>Customer</code></p></li></ul><p>Dan mungkin muncul insight seperti: &#8220;Kalau stok tidak cukup, event <code>OrderRejected</code> bisa muncul.&#8221;</p><p>Dari sini, kita mulai melihat pola <em>bounded context</em> dan logika bisnis yang nyata.</p><h3>3. <strong>Design-Level EventStorming</strong></h3><p>Tahap ini paling teknis, dilakukan biasanya oleh engineer dan arsitek sistem.<br>Di sini, event dan command diterjemahkan ke dalam komponen desain seperti:</p><ul><li><p><strong>Aggregate</strong> (logika domain utama)</p></li><li><p><strong>Saga / Process Manager</strong> (mengatur alur lintas aggregate)</p></li><li><p><strong>Read Model / Projection</strong> (untuk query data)</p></li><li><p><strong>External System Integration</strong> (pihak ketiga)</p></li></ul><p>Contoh dalam Rust (sketsa sederhana):</p><pre><code><code>struct Order {
    id: u64,
    status: OrderStatus,
}

impl Order {
    fn place(&amp;mut self) -&gt; OrderPlaced {
        self.status = OrderStatus::Placed;
        OrderPlaced { order_id: self.id }
    }
}

struct OrderPlaced {
    order_id: u64,
}</code></code></pre><p>Dari event yang awalnya hanya sticky note oranye, kini kita bisa melihat <em>kode yang berbicara dengan bahasa bisnis yang sama.</em></p><h2>Temuan yang Sering Muncul dari EventStorming</h2><p>EventStorming bukan hanya latihan pemetaan, ini adalah <em>alat diagnosis organisasi.</em></p><p>Beberapa temuan umum:</p><ul><li><p><strong>Ambiguitas istilah:</strong> orang berbeda menyebut hal yang sama dengan istilah berbeda.</p></li><li><p><strong>Kekosongan tanggung jawab:</strong> ada event tanpa command yang jelas.</p></li><li><p><strong>Masalah komunikasi antar tim:</strong> event muncul di satu context tapi dikonsumsi di context lain tanpa koordinasi.</p></li><li><p><strong>Aturan bisnis tersembunyi:</strong> &#8220;oh ternyata itu otomatis dibatalkan kalau lewat 24 jam!&#8221;</p></li></ul><p>Setiap temuan seperti ini adalah <em>pengetahuan domain baru</em>, dan itulah nilai utama EventStorming.</p><h2>Nilai Praktis bagi Engineer</h2><p>Bagi engineer, EventStorming terasa seperti cheat code untuk memahami domain baru.</p><p>Alih-alih membaca dokumen setebal 50 halaman atau menebak-nebak lewat backlog Jira, kita bisa melihat <strong>alur bisnis hidup</strong> di depan mata.</p><p>Kita tahu:</p><ul><li><p>Event apa yang penting,</p></li><li><p>Siapa yang memicunya,</p></li><li><p>Kondisi apa yang menyebabkannya gagal,</p></li><li><p>Dan bagaimana satu bounded context memengaruhi yang lain.</p></li></ul><p>Setelah workshop, kode yang kita tulis jadi jauh lebih dekat dengan cara bisnis berpikir.</p><h2>EventStorming dan Bounded Context</h2><p>Salah satu hasil alami dari EventStorming adalah munculnya <strong>pola pemisahan alami</strong> antar bagian domain.</p><p>Ketika papan mulai &#8220;penuh&#8221;, kita bisa mulai melihat klaster event yang saling erat, itulah kandidat <strong>bounded context.</strong></p><blockquote><p>&#8220;Bounded contexts don&#8217;t come from architects &#8212; they emerge from understanding.&#8221; &#8212; <em>Vlad Khononov, 2022</em></p></blockquote><p>Bounded context yang ditemukan dengan cara ini jauh lebih realistis, karena tumbuh dari percakapan lintas tim, bukan dari diagram PowerPoint.</p><h2>Kapan Menggunakan EventStorming</h2><p>Gunakan EventStorming ketika:</p><ul><li><p>Tim baru akan memulai proyek besar,</p></li><li><p>Domain masih kabur atau penuh asumsi,</p></li><li><p>Ada ketegangan antar tim atau model yang tidak selaras,</p></li><li><p>Atau ketika organisasi ingin membangun <em>ubiquitous language.</em></p></li></ul><p>Sebaliknya, untuk sistem kecil atau domain yang sudah stabil, EventStorming mungkin berlebihan, cukup gunakan diagram alur sederhana.</p><div><hr></div><h2>Tips Memfasilitasi EventStorming</h2><ol><li><p><strong>Mulai dari event, bukan dari entitas.</strong><br>Jangan tanya &#8220;objek apa yang kita punya?&#8221;, tapi &#8220;apa yang terjadi?&#8221;</p></li><li><p><strong>Dorong partisipasi semua pihak.</strong><br>Tidak ada jawaban salah. Justru ketidaksepakatan itu bahan diskusi.</p></li><li><p><strong>Gunakan papan besar dan sticky notes.</strong><br>Visualisasi itu penting, otak manusia lebih cepat memahami pola.</p></li><li><p><strong>Beri ruang untuk chaos.</strong><br>Di awal pasti berantakan, tapi dari kekacauan itu muncul struktur.</p></li><li><p><strong>Akhiri dengan insight, bukan diagram sempurna.</strong><br>Tujuan utama: pemahaman bersama, bukan artefak yang rapi.</p></li></ol><h2>Ringkasnya, ini adalah Percakapan yang Mengubah Cara Berpikir</h2><p>EventStorming bukan alat teknis, ia alat manusiawi.<br>Ia mengubah cara tim memahami domain dari <em>debat tentang solusi</em> menjadi <em>percakapan tentang kejadian nyata.</em></p><p>Setelah workshop, semua orang, baik engineer, PM, maupun ahli bisnis, akan mulai berbicara dengan bahasa yang sama. Dan itu, dalam semangat DDD, adalah kemenangan terbesar.</p><blockquote><p>&#8220;Software design is a communication game. EventStorming makes the rules visible.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Evolving Design Decisions, Menuju Desain yang Tumbuh Bersama Pengetahuan]]></title><description><![CDATA[Di artikel-artikel sebelumnya, kita belajar bahwa domain model itu hidup.]]></description><link>https://www.0-1.my.id/p/evolving-design-decisions-menuju</link><guid isPermaLink="false">https://www.0-1.my.id/p/evolving-design-decisions-menuju</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Mon, 20 Oct 2025 16:43:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p>Di artikel-artikel sebelumnya, kita belajar bahwa domain model itu hidup. Ia berkembang seiring perubahan bisnis dan pemahaman tim.</p><p>Tapi bukan hanya <strong>model domain</strong> yang perlu berevolusi. Keputusan desain dan arsitektur pun harus mengikuti &#8212; karena yang kita tahu hari ini <em>belum tentu benar besok.</em></p><blockquote><p>&#8220;Good design decisions are not permanent. They are just good for now.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><p>Inilah inti dari bab ini: <strong>desain yang baik adalah desain yang bisa tumbuh bersama waktu dan pengetahuan.</strong></p><h2>Mengapa Desain Harus Berevolusi</h2><p>Kita sering berpikir desain itu seperti kontrak: sekali diputuskan, harus dijaga mati-matian. Padahal, dunia bisnis bergerak cepat. Aturan baru muncul, model berubah, skala sistem bertambah, bahkan teknologi pun bergeser.</p><p>Keputusan yang dulu tepat bisa jadi tidak relevan hari ini. Maka, desain yang sehat bukan yang &#8220;tidak berubah&#8221;, tapi yang <strong>mudah berubah tanpa menyakitkan.</strong></p><h3>Contoh sederhana:</h3><p>Awalnya sistem pembayaran hanya mendukung <em>cash</em> dan <em>transfer bank</em>, jadi cukup enum sederhana:</p><pre><code>enum PaymentMethod {
    Cash,
    BankTransfer,
}</code></pre><p>Tiga bulan kemudian, muncul kebutuhan baru: <em>QRIS, kartu kredit, e-wallet,</em> bahkan <em>voucher internal.</em></p><p>Kalau arsitektur kita kaku, perubahan kecil seperti ini bisa menyentuh banyak tempat sekaligus &#8212; error di mana-mana. Tapi kalau modelnya fleksibel, kita cukup menambah varian baru tanpa mengubah bagian lain:</p><pre><code>enum PaymentMethod {
    Cash,
    BankTransfer,
    CreditCard(String),
    EWallet(String),
    Voucher(String),
}</code></pre><p>Desain yang bisa berevolusi seperti ini menunjukkan bahwa arsitektur kita <strong>adaptif terhadap perubahan pengetahuan.</strong></p><h2>Desain Itu Proses Pembelajaran</h2><p>Khononov menjelaskan bahwa desain bukan hasil akhir dari perencanaan panjang, melainkan <strong>hasil iterasi dari proses belajar.</strong></p><p>Setiap diskusi dengan domain expert, setiap bug, dan setiap perilaku pengguna membawa <em>insight baru</em> tentang domain. Dengan setiap wawasan baru itu, kita perlu memperbarui model, dan kadang mengubah keputusan desain sebelumnya.</p><blockquote><p>&#8220;Design is learning, and learning means change.&#8221; &#8212; <em>Vlad Khononov, 2022</em></p></blockquote><p>Desain DDD bukan soal menemukan struktur paling indah, tapi soal menemukan struktur <strong>yang paling menggambarkan kenyataan saat ini.</strong></p><h2>Perbedaan Antara Desain yang Kaku dan Desain yang Berevolusi</h2><p>Aspek Desain Kaku</p><ul><li><p>Fokus: Kepastian</p></li><li><p>Tujuan: Menghindari perubahan </p></li><li><p>Strategi: Rencana besar di awal</p></li><li><p>Efek samping: Cepat usang</p></li><li><p>Pola pikir: &#8220;Sudah benar dari awal&#8221;</p></li></ul><p>Aspek Desain Berevolusi </p><ul><li><p>Fokus: Adaptasi</p></li><li><p>Tujuan: Menyambut perubahan</p></li><li><p>Strategi: Iterasi kecil dan terus-menerus</p></li><li><p>Efek samping: Selalu relevan</p></li><li><p>Pola pikir: &#8220;Kita belajar setiap hari&#8221;</p></li></ul><p>Desain kaku lahir dari ketakutan akan salah. Desain yang berevolusi lahir dari <strong>rasa ingin tahu dan keberanian untuk mengoreksi diri.</strong></p><h2>Teknik: Menunda Keputusan Secara Sengaja</h2><p>Salah satu prinsip desain penting yang diperkenalkan dalam buku ini adalah <strong>delaying decisions</strong> &#8212; <em>menunda keputusan desain sampai kita punya cukup informasi.</em></p><p>Istilah ini sering disebut <em>Last Responsible Moment</em>:</p><blockquote><p>&#8220;Ambil keputusan selambat mungkin, tapi tidak sampai terlambat.&#8221;</p></blockquote><p>Artinya, jangan buat keputusan desain besar saat masih banyak ketidakpastian. Ambil keputusan yang paling ringan dulu, yang bisa dengan mudah diubah nanti.</p><p><strong>Contoh:</strong> Daripada langsung memilih pattern besar seperti <em>CQRS + Event Sourcing</em>, mulailah dengan <em>Layered Architecture</em>. Begitu sistem makin kompleks dan kebutuhan audit muncul, kamu bisa evolusikan jadi <em>CQRS.</em></p><p>Atau, daripada menentukan teknologi database di awal, abstraksikan akses datanya lewat <em>Repository Interface</em>. Kalau nanti migrasi dari SQLite ke PostgreSQL, domain model tetap aman.</p><pre><code>trait OrderRepository {
    fn save(&amp;self, order: &amp;Order);
    fn find_by_id(&amp;self, id: u64) -&gt; Option&lt;Order&gt;;
}</code></pre><p>Keputusan kecil ini menjaga fleksibilitas tanpa mengorbankan arah.</p><h2>Prinsip: Keputusan Harus Proporsional dengan Pengetahuan</h2><p>Khononov menyebut bahwa setiap keputusan desain adalah <strong>pertukaran antara pengetahuan dan risiko.</strong></p><ul><li><p>Semakin sedikit pengetahuan yang kita punya, semakin besar risiko salah mengambil keputusan.</p></li><li><p>Maka, keputusan harus <strong>sepadan dengan tingkat pemahaman kita saat itu.</strong></p></li></ul><p>Jangan terlalu dini membuat keputusan besar atas asumsi mentah. Sebaliknya, jangan juga terlalu lama menunda hingga tim kehilangan arah.</p><p>Prinsip ini mendorong pola pikir <em>evolutionary architecture</em>, arsitektur yang tidak selesai di atas kertas, melainkan terus dibentuk dari pengalaman nyata.</p><h2>Tanda-tanda Kamu Butuh Mengubah Desain</h2><ol><li><p><strong>Banyak &#8220;if&#8221; di mana-mana.</strong> Itu tanda model sudah tidak mencerminkan domain lagi.</p></li><li><p><strong>Aturan bisnis sulit dijelaskan lewat kode.</strong> Mungkin modelmu sudah terlalu teknis.</p></li><li><p><strong>Istilah di kode dan di meeting mulai berbeda.</strong> Bahasa umum (ubiquitous language) sudah melenceng.</p></li><li><p><strong>Perubahan kecil memengaruhi banyak bagian.</strong> Tanda struktur sistem sudah terlalu rapuh.</p></li><li><p><strong>Tim mulai takut refactor.</strong> Ini gejala klasik desain yang membatu.</p></li></ol><p>Kalau ini mulai terasa, jangan panik. Itu bukan kegagalan, itu sinyal bahwa kamu sudah belajar sesuatu yang baru, dan saatnya model ikut berubah.</p><h2>Pendekatan: Continuous Refinement</h2><p>Evolusi desain tidak butuh revolusi besar setiap enam bulan. Cukup lakukan <strong>refinement kecil</strong> secara terus-menerus.</p><p>Langkah sederhananya:</p><ol><li><p><strong>Identifikasi pain point.</strong> Misalnya entitas tertentu jadi terlalu besar.</p></li><li><p><strong>Diskusikan dengan domain expert.</strong> Apakah ada istilah atau proses baru?</p></li><li><p><strong>Perbaiki model.</strong> Pecah aggregate, ubah value object, atau tambahkan event.</p></li><li><p><strong>Uji asumsi.</strong> Pastikan perubahan benar-benar memudahkan pemahaman bisnis.</p></li><li><p><strong>Rilis kecil.</strong> Jangan tunda sampai &#8220;semua siap&#8221;.</p></li></ol><p>Refinement yang berkelanjutan jauh lebih sehat daripada <em>refactor masif</em> yang menakutkan.</p><h2>Mengelola Tekanan dan Trade-off</h2><p>Kadang manajemen ingin keputusan cepat: &#8220;Pilih framework sekarang!&#8221; Atau: &#8220;Kita harus finalkan model minggu ini!&#8221;</p><p>Dalam konteks DDD, tugas engineer bukan hanya membuat kode, tapi juga <strong>melindungi proses belajar.</strong> Artinya, jangan biarkan tekanan waktu membunuh kesempatan untuk memahami domain dengan benar.</p><p>Kita boleh mengambil keputusan pragmatis sementara &#8212; asal sadar bahwa itu keputusan <em>sementara</em>, dan siap diperbaiki nanti.</p><blockquote><p>&#8220;Every temporary decision is a debt &#8212; pay it back when knowledge grows.&#8221; &#8212; <em>Vlad Khononov, 2022</em></p></blockquote><h2>Kode Sebagai Dokumentasi Evolusi</h2><p>Model domain yang baik seharusnya menjadi dokumentasi hidup tentang cara bisnis bekerja <em>saat ini</em>. Jangan takut kalau modelmu berbeda dari enam bulan lalu &#8212; itu tanda kamu belajar.</p><p>Gunakan git commit, test case, dan domain event sebagai <em>jejak sejarah evolusi</em> keputusan desain.</p><p>Contoh:</p><pre><code>// Sebelum
enum DeliveryStatus {
    Pending,
    Delivered,
}

// Setelah memahami proses retur
enum DeliveryStatus {
    Pending,
    Delivered,
    Returned(String), // alasan pengembalian
}</code></pre><p>Setiap perubahan semacam ini adalah bukti bahwa sistemmu menyesuaikan diri dengan realitas bisnis, bukan sebaliknya.</p><h2>Ringkasan mengenai Desain yang Tumbuh Bersama Pengetahuan</h2><p>DDD bukan hanya tentang membuat model domain, tapi tentang <strong>membangun sistem yang terus belajar</strong>.</p><p>Desain yang baik tidak kaku. Ia tumbuh bersama tim, bersama bisnis, dan bersama waktu.</p><p>Prinsip utamanya sederhana:</p><ul><li><p>Jangan kunci keputusan sebelum waktunya.</p></li><li><p>Jangan takut mengubah arah saat pengetahuan bertambah.</p></li><li><p>Dan yang paling penting: pastikan perubahan desain selalu mengikuti <strong>makna bisnis</strong>, bukan sekadar selera teknis.</p></li></ul><blockquote><p>&#8220;The best design is the one that fits the current understanding of the domain &#8212; and is ready to change when that understanding grows.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Design Heuristics Dimana Saat Harus Realistis dengan Domain-Driven Design]]></title><description><![CDATA[Jika di pembahasan sebelumnya kita belajar tentang semua elemen keren di DDD &#8212; dari bounded context, aggregate, sampai communication patterns, mungkin kini muncul pertanyaan praktis:]]></description><link>https://www.0-1.my.id/p/design-heuristics-dimana-saat-harus</link><guid isPermaLink="false">https://www.0-1.my.id/p/design-heuristics-dimana-saat-harus</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sun, 19 Oct 2025 15:57:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p>Jika di pembahasan sebelumnya kita belajar tentang semua elemen keren di DDD &#8212; dari <em>bounded context</em>, <em>aggregate</em>, sampai <em>communication patterns</em>, mungkin kini muncul pertanyaan praktis:</p><blockquote><p>&#8220;Kapan sih kita <em>benar-benar perlu</em> pakai DDD? Apakah semua bagian sistem harus pakai domain model penuh?&#8221;</p></blockquote><p>Jawabannya singkat tapi penting: <strong>tidak selalu.</strong> Dan di sinilah kita mulai masuk ke inti bab ini: <em>design heuristics</em> &#8212; kumpulan prinsip berpikir agar kita tahu <strong>seberapa dalam menerapkan DDD</strong>, dan kapan harus <em>berhenti sebelum berlebihan.</em></p><h2>Heuristik: Bukan Aturan, Tapi Kompas</h2><p>Kata <em>heuristic</em> berarti &#8220;petunjuk praktis untuk membuat keputusan yang baik dalam kondisi tidak pasti.&#8221; Dalam konteks DDD, heuristik membantu kita memilih pendekatan desain yang <strong>seimbang antara nilai bisnis dan biaya implementasi.</strong></p><p>DDD bukan dogma. Ia bukan tentang &#8220;semua harus punya domain model lengkap.&#8221; Ia adalah <em>cara berpikir</em> agar sistem kita mencerminkan realitas bisnis <strong>secukupnya</strong> &#8212; tidak kurang, tapi juga tidak berlebihan.</p><blockquote><p>&#8220;Heuristics are not rules &#8212; they are good advice for most situations.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2>Prinsip Dasar 1: Gunakan Kompleksitas dengan Bijak</h2><p>DDD diciptakan untuk <strong>domain yang kompleks secara bisnis</strong>, bukan sekadar teknis. Kalau sistem kamu hanya memindahkan data antar tabel tanpa aturan khusus, maka DDD penuh justru akan memperlambat tim.</p><p>Bayangkan sistem sederhana seperti <em>user management</em>, <em>login</em>, atau <em>report generator</em>. Fungsi-fungsi itu bisa selesai dengan cepat pakai pola <em>Transaction Script</em> atau <em>Active Record</em>.</p><p>Tapi ketika mulai muncul hal-hal seperti:</p><ul><li><p>&#8220;kalau pengguna premium, logika perhitungan komisinya berbeda,&#8221;</p></li><li><p>&#8220;status langganan berubah otomatis tergantung perilaku,&#8221;</p></li><li><p>&#8220;ada peraturan bisnis yang saling bertabrakan,&#8221;</p></li></ul><p>maka itu tanda domain mulai <strong>kompleks</strong>. Dan di situlah <em>Domain Model</em> menjadi alat yang tepat.</p><blockquote><p>Heuristik #1: <strong>Semakin kompleks logika bisnis, semakin layak DDD digunakan.</strong></p></blockquote><h2>Prinsip Dasar 2: Model Harus Menghasilkan Nilai Bisnis</h2><p>Kadang engineer terjebak membangun model yang indah tapi tidak berdampak. DDD tidak mengejar keindahan teknis, tapi <strong>kejelasan makna bisnis.</strong></p><p>Sebelum membuat entitas, aggregate, atau event, selalu tanyakan:</p><blockquote><p>&#8220;Apakah model ini membantu tim memahami atau memecahkan masalah bisnis?&#8221;</p></blockquote><p>Kalau jawabannya tidak, mungkin kamu sedang membuat <em>arsitektur demi arsitektur.</em></p><p><strong>Contoh sederhana:</strong></p><p>Katakan kita sedang membangun sistem pembelian tiket.</p><p>Model yang bermanfaat:</p><pre><code>struct Ticket {
    id: u64,
    status: TicketStatus,
}

enum TicketStatus {
    Reserved,
    Paid,
    Cancelled,
}
</code></pre><p>Model yang &#8220;terlalu DDD tapi tidak berguna&#8221;:</p><pre><code>struct TicketAggregate {
    id: u64,
    ticket_entity: TicketEntity,
    ticket_state: TicketState,
    ticket_repository: Arc&lt;dyn Repository&gt;,
}</code></pre><p>Yang satu berbicara tentang <em>tiket dan statusnya</em>, yang lain berbicara tentang <em>framework dan istilah arsitektur</em>. Model yang baik selalu dekat dengan <em>bahasa domain</em>, bukan dengan jargon teknis.</p><blockquote><p>Heuristik #2: <strong>Model yang baik berbicara dalam bahasa bisnis, bukan bahasa framework.</strong></p></blockquote><h2>Prinsip Dasar 3: Pisahkan Domain yang Penting dari yang Biasa</h2><p>Tidak semua bagian sistem punya nilai strategis yang sama. Beberapa bagian adalah <strong>core domain</strong> &#8212; di sanalah keunggulan kompetitif bisnis berada. Yang lain hanyalah <strong>supporting</strong> atau bahkan <strong>generic subdomain</strong>.</p><p>Gunakan tenaga DDD di tempat yang paling berdampak.</p><p>Jenis Domain Fokus Pendekatan <strong>Core Domain</strong> Inovasi, keunggulan kompetitif Domain Model penuh (DDD taktis lengkap) <strong>Supporting Domain</strong> Mendukung operasi Pola sederhana seperti Active Record <strong>Generic Domain</strong> Umum untuk semua bisnis Gunakan library atau SaaS</p><p>Contoh nyata:</p><ul><li><p>Core Domain: algoritme rekomendasi di e-commerce.</p></li><li><p>Supporting Domain: sistem pembayaran internal.</p></li><li><p>Generic Domain: login, autentikasi, logging.</p></li></ul><blockquote><p>Heuristik #3: <strong>Investasikan DDD di tempat yang memberi nilai strategis terbesar.</strong></p></blockquote><h2>Prinsip Dasar 4: Jangan Jadikan DDD Sebagai Target, Tapi Sebagai Alat</h2><p>Engineer yang baru mengenal DDD sering terlalu semangat: semua hal dibuat Aggregate, semua entitas punya Repository, semua event dicatat.</p><p>Padahal DDD bukan checklist, melainkan <em>toolbox.</em> Gunakan hanya alat yang relevan untuk masalah di depan mata.</p><blockquote><p>Heuristik #4: <strong>DDD bukan tujuan akhir, melainkan sarana untuk memahami dan menyelesaikan kompleksitas.</strong></p></blockquote><p>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 <em>bisnis</em>, bukan tentang kode.</p><h2>Prinsip Dasar 5: Evolve, Don&#8217;t Freeze</h2><p>Model domain bukan kontrak permanen. Ia seharusnya <strong>tumbuh bersama pemahaman bisnis.</strong></p><p>Ketika aturan bisnis berubah, biarkan model ikut berevolusi. Jangan terjebak pada rasa takut &#8220;merusak arsitektur yang sudah rapi.&#8221;</p><blockquote><p>Heuristik #5: <strong>Model yang hidup lebih berguna daripada model yang sempurna.</strong></p></blockquote><p>Misalnya, awalnya kamu hanya punya dua status pembayaran: <code>Pending</code> dan <code>Paid</code>. Lalu muncul kebutuhan &#8220;Refunded&#8221;. Tambahkan saja, meskipun awalnya belum semua proses mendukung.</p><pre><code>enum PaymentStatus {
    Pending,
    Paid,
    Refunded,
}</code></pre><p>Model berkembang, pengetahuan bertambah &#8212; persis seperti bisnisnya.</p><h2>Prinsip Dasar 6: Biarkan Bounded Context Mengatur Diri Sendiri</h2><p>Ketika sistem tumbuh besar, mudah tergoda membuat &#8220;model universal&#8221; yang bisa dipakai semua tim. Padahal itu berbahaya.</p><p>Model yang terlalu umum akan kehilangan makna di setiap konteks. Lebih baik setiap bounded context punya modelnya sendiri &#8212; walau istilahnya sama tapi maknanya berbeda.</p><p>Contoh nyata:</p><ul><li><p>Di <em>Sales Context</em>, &#8220;Customer&#8221; berarti orang yang membeli produk.</p></li><li><p>Di <em>Support Context</em>, &#8220;Customer&#8221; berarti orang yang sedang punya tiket bantuan aktif.</p></li></ul><p>Keduanya sah. Yang penting, mereka <strong>tidak saling memaksakan makna.</strong></p><blockquote><p>Heuristik #6: <strong>Hargai otonomi bounded context &#8212; lebih baik model ganda yang jelas daripada model tunggal yang membingungkan.</strong></p></blockquote><h2>Prinsip Dasar 7: Arsitektur Ada untuk Melayani Domain</h2><p>Jangan biarkan framework atau pola arsitektur membatasi desain domain. Ingat bahwa <em>model domain adalah pusat dari sistem,</em> bukan lapisan di bawah framework.</p><p>Kalau framework ORM memaksa semua entitas harus punya <code>id</code> integer, padahal di domain kamu lebih masuk akal pakai <code>code</code> sebagai identitas, maka ubahlah framework, bukan domainnya.</p><pre><code>struct Product {
    code: String, // Bukan ID auto-increment
    name: String,
}</code></pre><blockquote><p>Heuristik #7: <strong>Framework boleh diganti, domain tidak.</strong></p></blockquote><h2>Prinsip Dasar 8: Ubiquitous Language Adalah Tes Terbaik</h2><p>Kalau kamu ingin tahu seberapa sehat model domainmu, lihat bagaimana tim berbicara tentang bisnisnya.</p><p>Kalau engineer, PM, dan ahli domain bisa bicara tentang &#8220;Order&#8221;, &#8220;Refund&#8221;, dan &#8220;Shipment&#8221; tanpa kebingungan &#8212; artinya modelmu sudah bekerja. Kalau tiap meeting diwarnai &#8220;maksud kamu order yang di database atau order yang di API?&#8221;, artinya modelmu butuh perbaikan.</p><blockquote><p>Heuristik #8: <strong>Jika bahasa di kode dan di percakapan bisnis sama, kamu sedang menerapkan DDD dengan benar.</strong></p></blockquote><h2>Ringkasnya, Pragmatism is the Real DDD</h2><p>DDD bukan sekadar teori elegan untuk sistem besar. Ia adalah <em>cara berpikir</em> untuk memastikan bahwa software yang kita bangun <strong>selalu berbicara tentang bisnis, bukan sekadar data.</strong></p><p>Namun, setiap engineer yang matang tahu:</p><ul><li><p>Tidak semua sistem butuh domain model penuh,</p></li><li><p>Tidak semua konteks perlu aggregate,</p></li><li><p>Dan tidak semua tim siap hidup dengan kompleksitas DDD sejak hari pertama.</p></li></ul><p>Gunakan <em>heuristics</em> sebagai kompas, bukan peta mutlak. Tugas kita bukan membuat DDD sempurna, tapi membuat sistem yang <strong>bermakna, terpelihara, dan berumur panjang.</strong></p><blockquote><p>&#8220;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.&#8221; &#8212; Vlad Khononov, <em>Learning Domain-Driven Design</em> (2022)</p></blockquote><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Communication Patterns untuk Menyatukan Bahasa di Dunia yang Berbeda]]></title><description><![CDATA[Setelah kita membangun domain model yang kuat dan melindunginya dengan arsitektur yang rapi, kini muncul pertanyaan baru:]]></description><link>https://www.0-1.my.id/p/communication-patterns-untuk-menyatukan</link><guid isPermaLink="false">https://www.0-1.my.id/p/communication-patterns-untuk-menyatukan</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sat, 18 Oct 2025 16:54:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setelah kita membangun domain model yang kuat dan melindunginya dengan arsitektur yang rapi, kini muncul pertanyaan baru:</p><blockquote><p>&#8220;Bagaimana kalau model kita harus berkomunikasi dengan model dari tim lain?&#8221;</p></blockquote><p>Dalam organisasi besar, setiap tim biasanya bekerja di <strong>bounded context</strong> yang berbeda, masing-masing dengan bahasa, istilah, dan prioritasnya sendiri. Tantangannya adalah bagaimana <em>bounded context</em> ini bisa saling berbicara tanpa saling merusak model satu sama lain.</p><p>Di sinilah <strong>communication patterns</strong> dalam DDD berperan. Ia membantu kita <strong>menjembatani dunia yang berbeda</strong>, agar integrasi antar sistem tidak membuat domain model kita rusak atau kehilangan makna.</p><h2>Mengapa Komunikasi Itu Rumit</h2><p>Komunikasi antara bounded context bukan sekadar &#8220;kirim data lewat API&#8221;. Masalah sebenarnya bukan di teknologinya, tapi di <strong>perbedaan makna</strong>.</p><p>Bayangkan dua tim:</p><ul><li><p><strong>Tim Sales</strong> menggunakan istilah &#8220;Customer&#8221; untuk siapa pun yang pernah melakukan transaksi.</p></li><li><p><strong>Tim Support</strong> menyebut &#8220;Customer&#8221; hanya untuk pengguna aktif yang punya kontrak dukungan.</p></li></ul><p>Ketika kedua sistem bertukar data tentang <em>Customer</em>, data itu mungkin valid secara teknis, tapi salah makna secara bisnis. Itulah mengapa DDD menekankan bahwa komunikasi antar bounded context harus punya <strong>kontrak yang jelas</strong>, baik secara teknis maupun semantik.</p><h2>Hubungan Upstream dan Downstream</h2><p>Dalam DDD, hubungan antar bounded context digambarkan seperti aliran sungai:</p><ul><li><p><strong>Upstream</strong> &#8594; konteks yang <em>mengirim data atau keputusan</em>,</p></li><li><p><strong>Downstream</strong> &#8594; konteks yang <em>menerima dan menyesuaikan diri</em> dengan upstream.</p></li></ul><p>Hubungan ini penting karena menentukan <strong>arah pengaruh</strong>, siapa yang memengaruhi siapa.</p><h3>Contoh sederhana</h3><p>Misalnya ada dua tim:</p><ul><li><p><strong>Team Orders</strong> mengelola pemesanan pelanggan.</p></li><li><p><strong>Team Shipping</strong> mengurus pengiriman barang.</p></li></ul><p>Ketika pesanan dikonfirmasi, <strong>Orders</strong> mengirim event ke <strong>Shipping</strong> untuk memulai proses pengiriman.</p><pre><code>Orders (upstream) ---&gt; Shipping (downstream)</code></pre><p>Jika tim Orders mengubah format event tanpa koordinasi, tim Shipping akan terkena dampaknya. Jadi, downstream selalu <strong>lebih sensitif terhadap perubahan</strong> upstream. Inilah mengapa kita perlu <em>communication pattern</em> yang tepat, untuk mengatur dinamika semacam ini.</p><h2>Pola-Pola Komunikasi antar Context</h2><p>DDD memperkenalkan beberapa pola utama untuk menggambarkan cara bounded context saling berinteraksi. Masing-masing mencerminkan tingkat kolaborasi dan kekuasaan yang berbeda.</p><h3>1. Partnership</h3><p>Dalam <strong>Partnership</strong>, dua tim bekerja sangat erat, mereka berbagi tujuan dan menegosiasikan setiap perubahan bersama.</p><p>Mereka bisa dianggap &#8220;sekutu&#8221; yang membangun solusi bersama, dengan jadwal rilis dan kontrak yang disepakati dua arah.</p><blockquote><p>&#8220;Changes are negotiated together.&#8221; &#8212; Vlad Khononov (2022)</p></blockquote><p>Pola ini cocok bila dua sistem bergantung kuat satu sama lain dan punya siklus hidup yang sinkron. Misalnya antara tim &#8220;Billing&#8221; dan &#8220;Subscription&#8221; di platform SaaS.</p><p>Tantangannya: koordinasi butuh komunikasi intensif, jadi lebih cocok untuk organisasi kecil atau modul yang sangat terintegrasi.</p><h3>2. Customer&#8211;Supplier</h3><p>Dalam pola ini, <strong>supplier</strong> menyediakan data atau layanan yang digunakan oleh <strong>customer</strong>. Supplier biasanya memiliki kekuasaan lebih besar karena menentukan struktur data dan kontrak API.</p><blockquote><p>&#8220;When the supplier has the power.&#8221; &#8212; <em>Khononov (2022)</em></p></blockquote><p>Jika tim supplier berubah, tim customer harus menyesuaikan diri.</p><p>Untuk melindungi domain model-nya sendiri, tim customer bisa membuat <strong>Anticorruption Layer (ACL)</strong>, lapisan penerjemah antara model supplier dan model internalnya.</p><p><strong>Contoh:</strong></p><pre><code>// Model dari supplier (mungkin dari API eksternal)
struct ExternalOrder {
    order_id: String,
    value: f64,
}

// Model internal di domain kita
struct InternalOrder {
    id: u64,
    total: f64,
}

// Anticorruption Layer (penerjemah)
impl From&lt;ExternalOrder&gt; for InternalOrder {
    fn from(eo: ExternalOrder) -&gt; Self {
        InternalOrder { id: eo.order_id.parse().unwrap(), total: eo.value }
    }
}</code></pre><p>ACL memastikan model domain kita <strong>tidak terkontaminasi</strong> oleh model pihak lain. Domain kita tetap bersih, meskipun harus berinteraksi dengan dunia luar.</p><h3>3. Conformist</h3><p>Kadang, tim downstream <strong>tidak punya pilihan</strong> selain menyesuaikan diri sepenuhnya dengan upstream, baik format data, struktur model, maupun jadwal rilisnya.</p><p>Inilah pola <strong>Conformist</strong>. Pola ini sering muncul saat:</p><ul><li><p>Sistem upstream adalah produk eksternal atau pihak ketiga.</p></li><li><p>Atau tim downstream terlalu kecil untuk memengaruhi perubahan di upstream.</p></li></ul><p>Misalnya, sistem kita membaca data dari layanan pemerintah atau vendor eksternal &#8212; mau tidak mau, kita harus &#8220;conform&#8221;.</p><p>Walau kurang ideal, <em>Conformist</em> tetap bisa dikelola dengan baik asalkan dokumentasi kontraknya jelas.</p><h3>4. Open Host Service dan Published Language</h3><p>Kadang, satu bounded context melayani banyak konsumen. Daripada menyesuaikan diri dengan masing-masing, lebih efisien kalau dia menyediakan satu <strong>antarmuka publik yang stabil</strong>.</p><p>Pola ini disebut <strong>Open Host Service</strong>, dan bahasa komunikasinya disebut <strong>Published Language</strong>.</p><ul><li><p><em>Open Host Service</em> &#8594; API publik yang terbuka untuk konsumsi banyak sistem.</p></li><li><p><em>Published Language</em> &#8594; format data dan istilah yang disepakati (misalnya JSON schema, gRPC proto, atau message contract).</p></li></ul><p>Contoh sederhana:</p><pre><code>// Published Language: kontrak publik API
#[derive(serde::Serialize)]
struct OrderDto {
    order_id: u64,
    total: f64,
    status: String,
}</code></pre><p>Dengan <em>Published Language</em>, upstream tidak perlu menyesuaikan setiap downstream. Semua berkomunikasi lewat kontrak publik yang stabil, mirip seperti &#8220;bahasa diplomatik&#8221; antar negara.</p><h3>5. Separate Ways</h3><p>Tidak semua bounded context harus saling bicara. Kadang, lebih baik mereka <strong>berjalan sendiri-sendiri</strong> dengan domain model masing-masing.</p><p>Pola <strong>Separate Ways</strong> digunakan saat:</p><ul><li><p>Integrasi terlalu rumit dibanding manfaatnya,</p></li><li><p>Atau dua sistem hanya berbagi data secara sinkronisasi batch, bukan real-time.</p></li></ul><blockquote><p>&#8220;Sometimes the cost of integration outweighs the benefits.&#8221; &#8212; <em>Khononov (2022)</em></p></blockquote><p>Dalam praktiknya, ini justru bisa lebih efisien: tim jadi bebas bereksperimen dan merilis fitur tanpa bergantung satu sama lain.</p><h2>Menggunakan Context Map</h2><p>Untuk memvisualisasikan hubungan antar bounded context dan pola komunikasinya, DDD menggunakan <strong>Context Map</strong> &#8212; semacam peta hubungan antar tim atau sistem.</p><p>Contohnya:</p><pre><code>[Sales Context] ---&gt; [Shipping Context] ---&gt; [Support Context]
       |                   |                       |
    (Customer&#8211;Supplier)  (Partnership)         (Separate Ways)</code></pre><p>Context Map membantu kita menjawab:</p><ul><li><p>Siapa upstream, siapa downstream?</p></li><li><p>Pola komunikasi apa yang digunakan?</p></li><li><p>Siapa yang perlu berkoordinasi untuk perubahan?</p></li></ul><p>Dengan peta ini, arsitektur organisasi menjadi lebih transparan, dan konflik semantik bisa diantisipasi sejak awal.</p><h2>Ketika Komunikasi Gagal</h2><p>Kesalahan paling umum dalam integrasi antar context adalah menganggap komunikasi sekadar urusan teknis. Padahal, <em>communication patterns</em> adalah tentang <strong>hubungan antar manusia dan tim</strong>, bukan hanya antar sistem.</p><p>Masalah seperti:</p><ul><li><p>&#8220;API-nya berubah sepihak,&#8221;</p></li><li><p>&#8220;Istilah &#8216;customer&#8217; di mereka artinya beda,&#8221;</p></li><li><p>atau &#8220;Kita tidak tahu kapan upstream akan rilis versi baru,&#8221; semuanya berakar pada komunikasi lintas domain yang buruk.</p></li></ul><p>DDD mengajarkan bahwa solusi teknis harus lahir dari <strong>kesepahaman semantik dan kolaborasi antar tim.</strong></p><h2>Ringkasnya, Komunikasi yang Berarti</h2><p>Setiap bounded context adalah dunia kecil dengan bahasanya sendiri. Tapi dunia ini tidak bisa hidup sendirian, ia harus berbicara dengan dunia lain.</p><p>Communication patterns membantu kita menjaga agar percakapan itu <strong>bermakna dan sehat</strong>, bukan sekadar pertukaran data.</p><p>Arsitektur yang bagus melindungi model dari gangguan teknis, tapi komunikasi yang bagus melindungi model dari <strong>kesalahpahaman makna</strong>.</p><p>Dan pada akhirnya, seperti yang sering diingatkan Khononov: &#8220;Domain-Driven Design bukan hanya tentang model dan kode, tapi tentang orang-orang yang berbicara dengan bahasa yang sama.&#8221;</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Architecture Patterns untuk Menjaga Model Tetap Bersih]]></title><description><![CDATA[Sampai di artikel ini, kita sudah membangun model domain yang mencerminkan cara bisnis bekerja.]]></description><link>https://www.0-1.my.id/p/architecture-patterns-untuk-menjaga</link><guid isPermaLink="false">https://www.0-1.my.id/p/architecture-patterns-untuk-menjaga</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Fri, 17 Oct 2025 15:06:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sampai di artikel ini, kita sudah membangun model domain yang mencerminkan cara bisnis bekerja. Tapi muncul tantangan baru: bagaimana cara <strong>menjaga model itu tetap bersih</strong> ketika sistem kita tumbuh, framework berubah, dan kebutuhan makin kompleks?</p><p>Inilah peran <em>architecture patterns</em>, arsitektur perangkat lunak yang membantu memisahkan logika bisnis dari hal-hal teknis, agar domain model tidak tenggelam di tengah &#8220;kebisingan&#8221; infrastruktur.</p><h2>Arsitektur Itu Bukan Soal Layer Saja</h2><p>Kebanyakan engineer mendengar kata &#8220;arsitektur&#8221; lalu langsung berpikir tentang <em>layered architecture</em>, lapisan presentasi, logika bisnis, dan data. Padahal, arsitektur dalam konteks DDD bukan cuma soal membagi layer, tapi <strong>menentukan bagaimana model domain berinteraksi dengan bagian lain dari sistem.</strong></p><p>Arsitektur adalah <strong>cara menjaga agar domain model tetap berdaulat</strong>, tidak dikendalikan oleh framework, database, atau API eksternal.</p><blockquote><p>Dalam DDD, domain model adalah &#8220;raja&#8221;, dan arsitektur adalah istana yang melindunginya.</p></blockquote><h2>Mengapa Butuh Pola Arsitektur?</h2><p>Tanpa pola arsitektur yang jelas, kode domain akan cepat &#8220;tercemar&#8221; oleh hal-hal teknis. Awalnya mungkin cuma satu query SQL di dalam entitas, lalu satu logika HTTP handler di service. Lama-lama model domain kehilangan fokus, menjadi campuran antara logika bisnis, UI, dan infrastruktur.</p><p>Inilah yang menyebabkan <em>Big Ball of Mud</em>, sistem yang sulit dipahami karena semua bagian saling menempel tanpa batas yang jelas.</p><p>Pola arsitektur membantu kita menetapkan <strong>batas tanggung jawab (separation of concerns)</strong> antara:</p><ul><li><p>Domain logic (apa yang bisnis lakukan),</p></li><li><p>Application logic (kapan bisnis dijalankan),</p></li><li><p>dan Infrastructure logic (bagaimana bisnis dijalankan di dunia nyata).</p></li></ul><h2>Beberapa Pola Arsitektur Umum</h2><p>Buku Khononov (2022) membahas beberapa pola arsitektur yang sering digunakan dalam implementasi DDD: <strong>Layered Architecture</strong>, <strong>Ports and Adapters (Hexagonal Architecture)</strong>, dan <strong>CQRS</strong>. Mari kita bahas satu per satu dengan contoh sederhana.</p><h3>1. Layered Architecture, Struktur Paling Umum</h3><p>Arsitektur berlapis ini mungkin paling dikenal. Biasanya terdiri dari tiga atau empat lapisan:</p><pre><code>+------------------------+
|   Presentation Layer   |
+------------------------+
|   Application Layer    |
+------------------------+
|   Domain Layer         |
+------------------------+
|   Infrastructure Layer |
+------------------------+</code></pre><ul><li><p><strong>Presentation Layer</strong> Menangani interaksi dengan pengguna atau sistem lain (API, UI, CLI).</p></li><li><p><strong>Application Layer</strong> Mengatur <em>flow</em> atau urutan operasi &#8212; kapan bisnis dieksekusi.</p></li><li><p><strong>Domain Layer</strong> Tempat Entity, Value Object, dan Domain Service berada.</p></li><li><p><strong>Infrastructure Layer</strong> Berisi detail teknis seperti database, file system, atau network.</p></li></ul><p><strong>Contoh sederhana (Rust):</strong></p><pre><code>// Domain Layer
struct Order {
    id: u64,
    total: f64,
}

impl Order {
    fn confirm(&amp;mut self) {
        println!("Order {} dikonfirmasi", self.id);
    }
}

// Application Layer
fn confirm_order(order_repo: &amp;mut impl OrderRepository, id: u64) {
    if let Some(mut order) = order_repo.find_by_id(id) {
        order.confirm();
        order_repo.save(order);
    }
}

// Infrastructure Layer
trait OrderRepository {
    fn find_by_id(&amp;self, id: u64) -&gt; Option&lt;Order&gt;;
    fn save(&amp;mut self, order: Order);
}</code></pre><p>Layered architecture mudah dipahami, cocok untuk banyak aplikasi. Namun, jika tidak dijaga dengan disiplin, lapisan bisa bocor, logika bisnis sering naik ke Application Layer atau turun ke Infrastructure Layer.</p><h3>2. Ports and Adapters (Hexagonal Architecture)</h3><p>Kadang disebut juga <strong>Hexagonal Architecture</strong>, pola ini dikembangkan oleh Alistair Cockburn. Tujuannya: <strong>memisahkan domain dari dunia luar</strong> lewat <em>port</em> (antarmuka) dan <em>adapter</em> (implementasi teknis).</p><p>Bayangkan domain sebagai inti heksagon, dan setiap sisi dihubungkan oleh &#8220;port&#8221; yang bisa dipasang atau dilepas sesuai kebutuhan: API, database, atau event queue.</p><pre><code>           +-----------------------+
           |    Presentation API   |
           +-----------+-----------+
                       |
         +-------------+-------------+
         |       Domain Core         |
         | (Entities, Services, etc) |
         +-------------+-------------+
                       |
           +-----------+-----------+
           | Infrastructure / DB   |
           +-----------------------+</code></pre><p><strong>Kuncinya:</strong> Domain tidak tahu siapa yang memanggilnya, dan tidak peduli siapa yang menyimpan datanya.</p><p><strong>Contoh sederhana (Rust):</strong></p><pre><code>// Port (interface)
trait PaymentGateway {
    fn pay(&amp;self, amount: f64) -&gt; bool;
}

// Domain core
struct PaymentService&lt;'a&gt; {
    gateway: &amp;'a dyn PaymentGateway,
}

impl&lt;'a&gt; PaymentService&lt;'a&gt; {
    fn process(&amp;self, amount: f64) {
        if self.gateway.pay(amount) {
            println!("Pembayaran berhasil!");
        } else {
            println!("Pembayaran gagal.");
        }
    }
}

// Adapter (implementasi)
struct FakeGateway;

impl PaymentGateway for FakeGateway {
    fn pay(&amp;self, _amount: f64) -&gt; bool {
        true
    }
}</code></pre><p>Dengan pola ini, kita bisa mengganti implementasi <em>PaymentGateway</em> tanpa menyentuh kode domain. Mau pakai Midtrans, Stripe, atau simulator lokal, tinggal ganti adapter-nya.</p><h3>3. CQRS (Command Query Responsibility Segregation)</h3><p>CQRS memisahkan dua jenis operasi utama sistem:</p><ul><li><p><strong>Command</strong> &#8594; mengubah data (buat, ubah, hapus).</p></li><li><p><strong>Query</strong> &#8594; membaca data.</p></li></ul><p>Tujuannya agar keduanya bisa berevolusi dengan kebutuhan berbeda, misalnya skala, performa, atau keamanan.</p><p>Dalam sistem sederhana, Command dan Query bisa digabung. Tapi dalam sistem kompleks, pemisahan ini membuat sistem lebih efisien dan mudah dioptimasi.</p><p><strong>Contoh sederhana (Rust):</strong></p><pre><code>// Command handler
fn confirm_order(order_repo: &amp;mut impl OrderRepository, id: u64) {
    if let Some(mut order) = order_repo.find_by_id(id) {
        order.confirm();
        order_repo.save(order);
    }
}

// Query handler
fn get_order_details(order_repo: &amp;impl OrderRepository, id: u64) -&gt; Option&lt;Order&gt; {
    order_repo.find_by_id(id)
}</code></pre><p>Kita bisa punya dua pipeline terpisah, satu untuk memproses perubahan, satu untuk membaca data (misalnya dari cache atau database yang dioptimalkan untuk query). CQRS sering dikombinasikan dengan <em>Event Sourcing</em> agar setiap perubahan bisa dilacak dengan mudah.</p><h2>Memilih Pola yang Tepat</h2><p>Tidak ada arsitektur yang &#8220;paling benar.&#8221; Pola yang ideal tergantung dari:</p><ul><li><p><strong>Kompleksitas domain</strong>,</p></li><li><p><strong>Skala sistem</strong>,</p></li><li><p><strong>Kebutuhan integrasi</strong>, dan</p></li><li><p><strong>Tim yang mengelola.</strong></p></li></ul><p>Sebagai panduan umum:</p><ul><li><p>Gunakan <strong>Layered Architecture</strong> untuk sistem yang masih tumbuh.</p></li><li><p>Gunakan <strong>Hexagonal Architecture</strong> jika ingin model domain benar-benar independen dari framework atau infrastruktur.</p></li><li><p>Gunakan <strong>CQRS</strong> bila ada kebutuhan pemisahan beban baca/tulis yang signifikan.</p></li></ul><h2>Menghindari Arsitektur yang Membelenggu</h2><p>Sering kali engineer terjebak pada arsitektur yang mereka anggap &#8220;suci&#8221;, sampai akhirnya domain model malah dikorbankan demi mematuhi struktur. DDD justru sebaliknya: <strong>arsitektur harus melayani domain, bukan sebaliknya.</strong></p><p>Kuncinya adalah menjaga <em>boundaries</em> tetap jelas, tapi tidak kaku. Ketika model domain berkembang, arsitektur boleh ikut menyesuaikan, selama tujuannya sama: <strong>melindungi logika bisnis dari gangguan teknis.</strong></p><h2>Ringkasnya, Arsitektur Sebagai Penjaga Makna</h2><p>Arsitektur bukan tentang folder, file, atau diagram. Ia tentang <strong>cara melindungi makna bisnis</strong> di dalam sistem kita.</p><p>Layer, port, dan adapter hanyalah alat untuk memastikan kode kita tetap bercerita tentang <em>domain</em>, bukan tentang framework. Karena pada akhirnya, sistem yang paling bertahan lama bukan yang paling modern arsitekturnya, tapi yang paling setia pada makna bisnis yang dilayaninya.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Menyempurnakan dan Menumbuhkan Model Domain]]></title><description><![CDATA[Setelah kita membangun fondasi Domain Model, lengkap dengan Entity, Value Object, Aggregate, Repository, dan kawan-kawan, muncul pertanyaan besar berikutnya: &#8220;Bagaimana model domain kita tetap relevan ketika bisnis berubah?&#8221;]]></description><link>https://www.0-1.my.id/p/menyempurnakan-dan-menumbuhkan-model</link><guid isPermaLink="false">https://www.0-1.my.id/p/menyempurnakan-dan-menumbuhkan-model</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Thu, 16 Oct 2025 15:10:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p>Setelah kita membangun fondasi Domain Model, lengkap dengan Entity, Value Object, Aggregate, Repository, dan kawan-kawan, muncul pertanyaan besar berikutnya: &#8220;Bagaimana model domain kita tetap relevan ketika bisnis berubah?&#8221;</p><p>Di dunia nyata, bisnis tidak pernah diam. Aturan baru muncul, prioritas berubah, bahkan istilah yang dulu dianggap jelas bisa bergeser maknanya. Maka, Domain Model pun harus <strong>tumbuh dan berevolusi</strong>. Bab ini membahas bagaimana kita bisa menyempurnakan model tanpa membuat sistem runtuh.</p><h2>Model Domain Bukan Arsitektur Sekali Jadi</h2><p>Kesalahan umum dalam menerapkan DDD adalah menganggap domain model sebagai desain permanen. Padahal, model itu seharusnya hidup dan berubah mengikuti <strong>pemahaman baru tentang domain.</strong></p><p>Khononov (2022) menekankan bahwa DDD bukan tentang mencari model yang sempurna di awal, melainkan <strong>mendekati pemahaman yang lebih baik seiring waktu.</strong> Setiap diskusi dengan ahli domain, setiap bug, dan setiap fitur baru bisa memperkaya model kita.</p><p>Bayangkan model domain seperti peta kota. Saat pertama kali dibuat, mungkin hanya berisi jalan utama. Tapi seiring waktu, kita tambahkan gang kecil, lampu merah, dan area baru &#8212; bukan karena peta awal salah, tapi karena pengetahuan kita bertambah.</p><h2>Proses Refinement: Dari Model Kasar ke Model Tajam</h2><h3>1. Mulai dari Model Kasar</h3><p>Pada awal proyek, buatlah model sederhana dulu &#8212; tidak masalah kalau belum lengkap. Fokus pada pemahaman dasar: <em>apa saja konsep utama</em> dan <em>bagaimana mereka berhubungan</em>.</p><p>Misalnya kita membangun sistem untuk pengiriman paket. Model awal bisa sesederhana ini:</p><pre><code>struct Package {
    id: u64,
    status: String,
}

impl Package {
    fn deliver(&amp;mut self) {
        self.status = "Delivered".to_string();
    }
}</code></pre><p>Masih sederhana, tapi cukup untuk memulai percakapan dengan ahli domain.</p><h3>2. Kembangkan Melalui Umpan Balik</h3><p>Setiap kali bisnis atau stakeholder memberi masukan (&#8220;Bagaimana kalau pelanggan bisa menjadwalkan ulang pengiriman?&#8221;), kita ubah model agar mencerminkan realitas baru itu.</p><pre><code>enum DeliveryStatus {
    Pending,
    InTransit,
    Delivered,
    Rescheduled(String), // alasan atau tanggal baru
}

struct Package {
    id: u64,
    status: DeliveryStatus,
}</code></pre><p>Model berkembang mengikuti kebutuhan bisnis, <strong>bukan sebaliknya.</strong> Perubahan ini adalah bentuk <em>refinement</em>, bukan &#8220;refactor tanpa arah&#8221;.</p><h3>3. Evaluasi Bahasa Umum (Ubiquitous Language)</h3><p>Setiap istilah di model harus sama artinya bagi semua pihak, engineer, product owner, dan ahli domain.</p><p>Kalau tim mulai bilang &#8220;Shipment&#8221; di tempat yang seharusnya &#8220;Package&#8221;, itu tanda bahasa umum mulai kabur. Periksa model, ubah nama kelas, fungsi, dan variabel agar kembali konsisten dengan istilah bisnis yang terbaru.</p><p>Inilah kenapa DDD mendorong kode yang &#8220;bercerita seperti domain&#8221;-nya.</p><h2>Pola Umum dalam Evolusi Model</h2><h3>1. Split dan Merge Aggregate</h3><p>Saat sistem bertumbuh, aggregate yang dulu terasa ideal bisa jadi terlalu besar. Kita mungkin perlu memisahkannya agar tidak menimbulkan <em>transaction contention</em> atau <em>performance bottleneck</em>.</p><p>Misalnya awalnya kita punya <code>Order</code> yang juga menyimpan <code>Payment</code> dan <code>Shipment</code> di dalamnya. Tapi seiring waktu, tim pembayaran dan pengiriman berkembang terpisah.</p><p>Maka kita pisahkan menjadi tiga aggregate dengan batas yang jelas.</p><pre><code>// Awalnya semua di Order
struct Order {
    id: u64,
    payment_status: String,
    shipment_status: String,
}

// Setelah displit
struct Order {
    id: u64,
}

struct Payment {
    order_id: u64,
    status: String,
}

struct Shipment {
    order_id: u64,
    tracking_code: String,
}</code></pre><p>Kini setiap tim bisa berinovasi di domain-nya tanpa saling menunggu.</p><h3>2. Mengubah Entity menjadi Value Object (atau sebaliknya)</h3><p>Kadang sebuah objek awalnya dianggap penting secara identitas, tapi belakangan ternyata tidak.</p><p>Contoh: pada tahap awal, kita buat <code>Address</code> sebagai <code>Entity</code> karena kita pikir pengguna bisa memperbaruinya dan kita perlu menyimpannya secara unik. Tapi kemudian kita sadar bahwa <code>Address</code> hanya bagian dari <code>Order</code> dan tidak pernah digunakan secara terpisah.</p><p>Maka kita ubah menjadi <code>Value Object</code>.</p><pre><code>#[derive(Clone, PartialEq, Eq)]
struct Address {
    street: String,
    city: String,
    postal_code: String,
}</code></pre><p>Sebaliknya, jika suatu saat kita butuh melacak alamat pelanggan secara historis, <code>Address</code> bisa dipromosikan lagi menjadi <code>Entity</code>.</p><h3>3. Menambah Domain Event untuk Dekoupling</h3><p>Ketika sistem makin besar, modul-modul akan saling tergantung. Untuk mencegah kekacauan, kita bisa menambahkan <strong>Domain Event</strong> agar komunikasi antarmodul tidak saling menempel.</p><pre><code>struct OrderCreated {
    order_id: u64,
}

struct SendEmailOnOrderCreated;

impl SendEmailOnOrderCreated {
    fn handle(event: &amp;OrderCreated) {
        println!("Email konfirmasi untuk order {} dikirim!", event.order_id);
    }
}</code></pre><p>Dengan event, <code>Order</code> tidak perlu tahu cara mengirim email, dan modul notifikasi bisa bereaksi secara independen. Ini membuat sistem lebih fleksibel dan siap tumbuh tanpa coupling berlebihan.</p><h2>Evolusi yang Terarah, Bukan Reaktif</h2><p>Menumbuhkan model domain bukan berarti &#8220;sering ganti struktur kode&#8221;. Tujuannya bukan perubahan semata, tapi <strong>perubahan yang memperdalam pemahaman kita terhadap domain</strong>.</p><p>Langkah idealnya seperti ini:</p><ol><li><p><strong>Temukan masalah di dunia nyata.</strong> Misalnya pengguna bingung dengan istilah &#8220;shipment&#8221; vs &#8220;delivery&#8221;.</p></li><li><p><strong>Diskusikan dengan ahli domain.</strong> Pahami maknanya dalam konteks bisnis.</p></li><li><p><strong>Perbarui bahasa umum.</strong> Ubah nama kelas atau entitas agar konsisten dengan istilah baru.</p></li><li><p><strong>Refactor model.</strong> Pisahkan, gabungkan, atau ubah struktur sesuai pemahaman baru.</p></li><li><p><strong>Uji dan validasi.</strong> Pastikan perubahan tidak merusak perilaku bisnis yang sudah benar.</p></li></ol><p>Jika perubahan dilakukan lewat percakapan yang intens antara engineer dan ahli domain, model domain akan terus &#8220;mendekati kenyataan&#8221; seiring waktu.</p><h2>Kesalahan Umum Saat Model Berevolusi</h2><ol><li><p><strong>Refactor teknis tanpa konteks bisnis.</strong> Mengubah struktur hanya karena &#8220;terlihat lebih bersih&#8221;, padahal maknanya makin kabur.</p></li><li><p><strong>Terlalu cepat memecah aggregate.</strong> Split boleh dilakukan, tapi pastikan memang ada kebutuhan bisnis atau beban transaksi nyata.</p></li><li><p><strong>Mengabaikan bahasa umum.</strong> Nama-nama di kode harus tetap sejalan dengan istilah di dunia nyata, bukan dengan preferensi pribadi.</p></li><li><p><strong>Tidak mencatat keputusan.</strong> Setiap perubahan besar di domain model sebaiknya punya alasan bisnis yang terdokumentasi.</p></li></ol><h2>Menumbuhkan Model Secara Aman</h2><p>Dalam praktik modern, kita bisa menggunakan pendekatan seperti:</p><ul><li><p><strong>Feature toggles</strong>, untuk mengaktifkan model baru tanpa mengganggu produksi.</p></li><li><p><strong>Event sourcing</strong>, agar perubahan model tidak kehilangan jejak historis.</p></li><li><p><strong>Migration scripts</strong>, untuk memindahkan data lama ke struktur baru dengan aman.</p></li></ul><p>DDD tidak menentang perubahan, ia justru <strong>mengajarkan cara mengelolanya dengan sadar</strong>.</p><h2>Akhirnya: Model yang Hidup</h2><p>Domain model yang baik bukan yang paling indah diagramnya, tapi yang <strong>tetap bernapas bersama bisnisnya.</strong></p><p>Ketika bisnis berubah, model pun ikut beradaptasi. Ketika istilah baru muncul, kode pun ikut menyesuaikan. Dan ketika engineer dan ahli domain berbicara, mereka bicara dalam <strong>bahasa yang sama</strong>, bukan lagi sekadar query, tapi makna.</p><p>Itulah esensi menghadapi kompleksitas: Bukan melawannya dengan abstraksi berlebihan, tetapi <strong>menjinakkannya dengan pemahaman yang terus bertumbuh.</strong></p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Pola Logika Bisnis Kompleks dengan Model Domain]]></title><description><![CDATA[Kalau di artikel-artikel sebelumnya kita bicara tentang cara membatasi konteks (bounded context) dan mengintegrasikannya, sekarang kita masuk ke jantung dari Domain-Driven Design (DDD): Domain Model.]]></description><link>https://www.0-1.my.id/p/pola-logika-bisnis-kompleks-dengan</link><guid isPermaLink="false">https://www.0-1.my.id/p/pola-logika-bisnis-kompleks-dengan</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Wed, 15 Oct 2025 16:44:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kalau di artikel-artikel sebelumnya kita bicara tentang cara membatasi konteks (bounded context) dan mengintegrasikannya, sekarang kita masuk ke jantung dari Domain-Driven Design (DDD): <strong>Domain Model</strong>.<br>Bagian ini menjawab pertanyaan besar: &#8220;Bagaimana cara membuat kode yang benar-benar mencerminkan cara bisnis bekerja, bukan sekadar menyimpan data?&#8221;</p><h2>Dari Strategi ke Taktik</h2><p>Dalam DDD, ada dua lapisan pendekatan: <strong>Strategic DDD</strong> dan <strong>Tactical DDD</strong>.<br>Strategic DDD membantu kita memetakan <em>peta besar</em>, membagi sistem menjadi domain, subdomain, dan bounded context.<br>Sementara Tactical DDD berbicara tentang <em>bagaimana kita membangun isi di dalam satu bounded context itu.</em></p><p>Kalau Strategic DDD seperti membuat denah kota, maka Tactical DDD adalah merancang bangunan di dalam tiap distrik: siapa penghuni, bagaimana alurnya, dan aturan apa yang berlaku di dalamnya.</p><h2>Domain Model: Jantung dari DDD</h2><p>Sebuah <strong>domain model</strong> bukan sekadar diagram UML atau tabel database.<br>Ia adalah <strong>representasi konseptual dari cara bisnis bekerja</strong>, diterjemahkan ke dalam kode, menggunakan bahasa yang sama dengan yang digunakan oleh para ahli domain.</p><p>Model ini bukan hanya soal <em>data structure</em>, tapi juga soal <em>perilaku (behavior)</em> dan <em>aturan (rules)</em> yang melekat di dalamnya.</p><p>Contoh sederhana:<br>Bayangkan kita membuat sistem untuk toko online. Ada entitas <code>Order</code>, tapi <code>Order</code> bukan cuma tabel dengan kolom <code>id</code>, <code>total</code>, dan <code>status</code>.<br>Ia harus tahu bagaimana:</p><ul><li><p>menambahkan item,</p></li><li><p>menghitung total,</p></li><li><p>memastikan tidak ada duplikasi produk,</p></li><li><p>dan kapan pesanan bisa dikonfirmasi.</p></li></ul><p>Model yang baik berarti kode kita <em>bicara seperti bisnisnya</em>.</p><h2>Entity</h2><p>Salah satu elemen paling penting dari domain model adalah <strong>Entity</strong>, sebuah objek yang punya identitas unik dan bisa berubah seiring waktu.</p><p>Misalnya, <code>User</code> dengan ID <code>123</code> tetap sama orangnya meski alamat atau emailnya berubah.<br>Yang menentukan dirinya adalah identitas, bukan nilainya.</p><pre><code><code>struct User {
    id: u64,
    name: String,
    email: String,
}

impl User {
    fn change_email(&amp;mut self, new_email: String) {
        self.email = new_email;
    }
}</code></code></pre><p>Di sini <code>User</code> adalah Entity karena kita mengenalinya lewat <code>id</code>.<br>Ketika <code>change_email()</code> dipanggil, objek ini masih &#8220;orang yang sama&#8221;.</p><h2>Value Object</h2><p>Berbeda dengan Entity, <strong>Value Object</strong> tidak punya identitas.<br>Ia hanya penting karena nilainya. Dua objek yang nilainya sama dianggap sama.</p><p>Coba pikirkan <code>Money</code>, <code>Address</code>, atau <code>DateRange</code>.<br>Kalau kamu punya <code>Money { amount: 100, currency: &#8220;USD&#8221; }</code>, itu identik dengan objek lain yang punya nilai sama.</p><pre><code><code>#[derive(Debug, Clone, PartialEq, Eq)]
struct Money {
    amount: f64,
    currency: String,
}</code></code></pre><p>Value Object biasanya <strong>immutable</strong>, artinya nilainya tidak diubah, tapi dibuat baru saat ada perubahan.<br>Pendekatan ini membuat kode lebih aman dan mudah diprediksi.</p><h2>Aggregate</h2><p>Saat bisnis mulai kompleks, satu entitas tidak lagi cukup.<br>Kita butuh sekumpulan entitas dan value object yang bekerja bersama dalam satu batas konsistensi.<br>Inilah yang disebut <strong>Aggregate</strong>.</p><p>Aggregate adalah kumpulan objek yang <strong>dikelola sebagai satu kesatuan logis</strong>, dengan satu titik masuk utama yang disebut <strong>Aggregate Root</strong>.</p><pre><code><code>struct OrderItem {
    product_id: u64,
    quantity: u32,
}

struct Order {
    id: u64,
    items: Vec&lt;OrderItem&gt;,
}

impl Order {
    fn add_item(&amp;mut self, product_id: u64, quantity: u32) {
        self.items.push(OrderItem { product_id, quantity });
    }

    fn total_items(&amp;self) -&gt; usize {
        self.items.len()
    }
}</code></code></pre><p><code>Order</code> di atas adalah Aggregate Root &#8212; semua perubahan terhadap <code>OrderItem</code> harus melalui <code>Order</code>.<br>Aggregate membantu menjaga <strong>aturan bisnis tetap konsisten</strong> di dalam batasnya.</p><h2>Repository</h2><p>Domain Model tidak seharusnya tahu tentang database atau API.<br>Tapi tentu kita tetap perlu menyimpan data.<br>Untuk itu, DDD memperkenalkan <strong>Repository</strong>.</p><p>Repository berfungsi sebagai &#8220;pintu keluar masuk&#8221; Aggregate.<br>Dari sisi domain, Repository terlihat seperti <em>koleksi di memori</em>, meski di baliknya mungkin ada SQL, file, atau service eksternal.</p><pre><code><code>trait OrderRepository {
    fn save(&amp;self, order: &amp;Order);
    fn find_by_id(&amp;self, id: u64) -&gt; Option&lt;Order&gt;;
}</code></code></pre><p>Dengan pola ini, domain tetap bersih dari detail teknis.<br>Kita bisa mengganti penyimpanan dari SQLite ke PostgreSQL tanpa mengubah logika bisnis sedikit pun.</p><h2>Domain Service</h2><p>Kadang kita menemukan logika bisnis yang tidak cocok dimasukkan ke satu entitas mana pun.<br>Misalnya, proses transfer uang antar akun: melibatkan dua <code>Account</code>, tapi tidak ada satu pun yang benar-benar &#8220;memiliki&#8221; logika itu.</p><p>Inilah peran <strong>Domain Service</strong>, tempat untuk menaruh logika lintas entitas.</p><pre><code><code>struct Account {
    id: u64,
    balance: f64,
}

struct TransferService;

impl TransferService {
    fn transfer(from: &amp;mut Account, to: &amp;mut Account, amount: f64) {
        if from.balance &gt;= amount {
            from.balance -= amount;
            to.balance += amount;
        }
    }
}</code></code></pre><p>Domain Service tetap bagian dari domain layer, bukan service teknis seperti API handler atau queue worker.<br>Ia merepresentasikan <strong>aksi bisnis</strong>, bukan infrastruktur.</p><h2>Factory</h2><p>Membuat entitas kadang tidak sesederhana memanggil <code>new()</code>.<br>Ada validasi, aturan bisnis, atau dependensi lain.<br>Di sinilah <strong>Factory</strong> digunakan.</p><p>Factory bertugas <strong>membangun objek kompleks dengan aturan bisnis yang benar sejak awal.</strong></p><pre><code><code>struct OrderFactory;

impl OrderFactory {
    fn create_new(items: Vec&lt;OrderItem&gt;) -&gt; Order {
        assert!(!items.is_empty(), &#8220;Order harus punya minimal satu item&#8221;);
        Order { id: 0, items }
    }
}</code></code></pre><p>Factory mencegah kita membuat objek domain dalam keadaan &#8220;tidak valid&#8221;.<br>Ia seperti dapur yang memastikan masakan sudah matang sebelum dihidangkan.</p><h2>Domain Event</h2><p>Dalam kehidupan nyata, setiap sistem bisnis penuh dengan peristiwa: pesanan dibuat, pembayaran diterima, stok habis, dsb.<br>DDD merepresentasikan semua itu lewat <strong>Domain Event</strong>.</p><p>Event adalah sinyal bahwa <em>sesuatu yang penting sudah terjadi</em> di dalam domain.<br>Biasanya diberi nama dengan bentuk lampau: <code>OrderCreated</code>, <code>PaymentReceived</code>.</p><pre><code><code>struct OrderCreated {
    order_id: u64,
    timestamp: u64,
}
</code></code></pre><p>Event bisa dikirim ke bagian lain dari sistem (misalnya ke modul pengiriman atau notifikasi) tanpa membuat coupling langsung antar komponen.<br>Hasilnya: sistem lebih fleksibel dan modular.</p><h2>Menghadapi Kompleksitas</h2><p>Setiap sistem yang tumbuh pasti akan menjadi kompleks.<br>Tactical DDD memberi kita alat untuk <strong>mengelola</strong> kompleksitas itu, bukan menyingkirkannya.</p><ul><li><p>Entity dan Value Object membantu kita berpikir dalam istilah bisnis, bukan tabel.</p></li><li><p>Aggregate menjaga aturan tetap konsisten.</p></li><li><p>Repository dan Factory memisahkan logika domain dari teknis.</p></li><li><p>Domain Service dan Event membuat sistem bisa berkembang tanpa kekacauan.</p></li></ul><p>Inilah inti filosofi DDD: &#8220;Kode bukan cuma alat, tapi cerminan dari cara kita memahami bisnis.&#8221;</p><p>Ketika model domain dibuat dengan benar, engineer tidak hanya menulis kode, mereka <strong>mengkodekan pengetahuan bisnis</strong> yang bisa bertahan bertahun-tahun, bahkan ketika framework atau teknologi berubah.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Pola Logika Bisnis Sederhana dengan Transaction Script & Active Record]]></title><description><![CDATA[Saat logika bisnis belum terlalu rumit, kita bisa pakai pola Transaction Script atau Active Record.]]></description><link>https://www.0-1.my.id/p/pola-logika-bisnis-sederhana-dengan</link><guid isPermaLink="false">https://www.0-1.my.id/p/pola-logika-bisnis-sederhana-dengan</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Tue, 14 Oct 2025 15:12:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!sy3A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Saat logika bisnis belum terlalu rumit, kita bisa pakai pola <strong>Transaction Script</strong> atau <strong>Active Record</strong>. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sy3A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sy3A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sy3A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sy3A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!sy3A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f644851-dad9-4137-a6d8-7f68c59e9b6c_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Pola Logika Bisnis Sederhana dengan Transaction Script &amp; Active Record.</figcaption></figure></div><h2>Business Logic</h2><p>Logika bisnis (<em>business logic</em>) adalah bagian dari sistem yang menentukan bagaimana data diproses sesuai aturan dan tujuan bisnis<strong>.</strong></p><p>Secara definisi:</p><blockquote><p>Business logic adalah sekumpulan keputusan, kalkulasi, kondisi, dan alur kerja yang menjelaskan <em>bagaimana bisnis seharusnya beroperasi dalam konteks sistem perangkat lunak.</em></p></blockquote><p>Contoh:</p><ul><li><p>Jika saldo rekening &lt; 0 &#8594; tolak transaksi.</p></li><li><p>Jika pelanggan sudah bayar &#8594; ubah status pesanan menjadi &#8220;confirmed.&#8221;</p></li><li><p>Jika total belanja &gt; 1 juta &#8594; berikan diskon 10%.</p></li></ul><p>Semua ini bukan &#8220;aturan pemrograman umum,&#8221; tapi cara bisnis tertentu berjalan.<br>Karena itu, <em>business logic</em> berbeda dari <em>technical logic</em> (seperti validasi input, autentikasi pengguna, caching, dll.).</p><p>Intinya: logika bisnis = perilaku sistem yang mencerminkan keputusan bisnis.</p><h3>Business Rules</h3><p>Istilah Business Rules dan Business Logic ini sering tertukar, padahal secara konsep ada perbedaan:</p><ul><li><p> Business Rules</p><ul><li><p>Ciri utama: Prinsip atau kebijakan yang didefinisikan oleh organisasi, misalnya menjelaskan apa yang boleh dan tidak boleh terjadi di dunia nyata.</p></li><li><p>Contoh: Setiap transaksi harus memiliki nomor faktur unik.</p></li></ul></li><li><p>Business Logic</p><ul><li><p>Ciri utama: Implementasi teknis dari aturan-aturan tersebut di dalam sistem.</p></li><li><p>Contoh: <code>fn generate_invoice_id()</code> memastikan nomor faktur tidak duplikat.</p></li></ul></li></ul><p>Singkatnya:</p><ul><li><p><em>Business rules</em> = <strong>&#8220;aturan permainan&#8221;</strong> (bersifat deklaratif).</p></li><li><p><em>Business logic</em> = <strong>&#8220;cara memainkan permainan itu di sistem&#8221;</strong> (bersifat prosedural).</p></li></ul><p>Dalam DDD, keduanya sama-sama penting:</p><ul><li><p><em>Aturan bisnis</em> berasal dari pengetahuan ahli domain (domain expert).</p></li><li><p><em>Logika bisnis</em> diimplementasikan di kode (biasanya di entitas atau service dalam domain model).</p></li></ul><h2>Transaction Script</h2><p>Secara definisi, Transaction Script adalah pola arsitektur di mana setiap operasi bisnis diimplementasikan sebagai satu prosedur atau fungsi tunggal.<br>Istilah aslinya berasal dari <em>Patterns of Enterprise Application Architecture</em> oleh Martin Fowler (2003).</p><blockquote><p>Definisi: &#8220;Transaction Script organizes business logic by procedures where each procedure handles a single request from the presentation.&#8221;<br>&#8212; <em>Martin Fowler, P of EAA, 2003.</em></p></blockquote><p>Dengan kata lain:</p><ul><li><p>Setiap <em>use case</em> bisnis (misal &#8220;proses pembayaran&#8221;, &#8220;buat laporan&#8221;, &#8220;import data&#8221;) ditulis sebagai satu skrip atau fungsi.</p></li><li><p>Logika bisnis disusun secara imperatif (langkah demi langkah).</p></li><li><p>Tidak ada objek domain yang rumit &#8212; biasanya hanya sekumpulan operasi database.</p></li></ul><p>Analogi: seperti membuat resep dapur dalam satu lembar kertas, semua langkahnya berurutan: ambil bahan, masak, sajikan. Simpel, tapi sulit dipakai ulang kalau resep makin kompleks.</p><p>Khononov (2022) menjelaskan bahwa <em>Transaction Script</em> mengorganisir logika bisnis ke dalam prosedur terpisah. Setiap prosedur (atau fungsi) menangani satu permintaan atau operasi bisnis. </p><p>Misalnya, fungsi <code>process_payment()</code> yang hanya fokus menyelesaikan satu transaksi pembayaran. Pendekatan ini gampang dipahami dan minim abstraksi. Contohnya, bayangkan kita punya daftar pekerjaan (job) yang perlu diproses satu per satu:</p><pre><code><code>fn process_jobs(db: &amp;Database) {
    db.start_transaction();
    if let Some(job) = db.load_next_job() {
        let data = std::fs::read_to_string(&amp;job.source).unwrap();
        let result = convert_to_xml(&amp;data);
        std::fs::write(&amp;job.destination, result).unwrap();
        db.mark_complete(job.id);
    }
    db.commit();
}
</code></code></pre><p>Kode di atas menunjukkan satu prosedur sederhana: mulai transaksi, baca job berikutnya, ubah data, simpan hasil, lalu <em>commit</em>. Jika ada kesalahan di tengah, sistem harus <em>rollback</em> agar data tetap konsisten. </p><p>Khononov menegaskan pentingnya perilaku transaksional di setiap skrip: operasi harus sukses seluruhnya atau gagal tanpa meninggalkan kondisi setengah jadi. Karena itu, pola Transaction Script cocok untuk subdomain pendukung atau tugas <strong>ETL (Extract-Transform-Load)</strong> sederhana. Sebagai contoh, sinkronisasi data dari satu sistem ke sistem lain bisa diimplementasikan dengan skrip seperti di atas.</p><p><strong>Kapan pakai Transaction Script?</strong> Beberapa poin penting:</p><ul><li><p>Cocok untuk <em>subdomain pendukung</em> atau <em>generik</em> di mana logika bisnisnya prosedural (misal batch job, laporan, sinkronisasi).</p></li><li><p>Sederhana dan cepat: minim abstraksi, performa tinggi karena langsung panggil database (atau penyimpanan).</p></li><li><p><strong>Hati-hati:</strong> Jika logika bisnis makin kompleks, skrip terpisah cenderung duplikasi kode dan kesulitan pemeliharaan. Khononov bahkan menyebut pattern ini sering dianggap <em>antipola (antipattern)</em> karena bisa jadi &#8220;big ball of mud&#8221; jika dipakai di domain inti yang rumit. Jadi, jangan pakai Transaction Script untuk <em>core subdomain</em> yang punya banyak aturan bisnis, karena pola ini tidak tahan dengan kompleksitas tinggi.</p></li></ul><h3>Antipattern Arsitektur Big Ball of Mud</h3><p>Ini adalah antipattern arsitektur yang menggambarkan sistem tanpa struktur yang jelas.</p><blockquote><p><strong>Definisi:</strong> &#8220;A Big Ball of Mud is a haphazardly structured system, tangled, and difficult to maintain.&#8221;<br>&#8212; <em>Foote &amp; Yoder, 1997.</em></p></blockquote><p>Sederhananya:</p><ul><li><p>Semua kode bercampur tanpa batas yang jelas.</p></li><li><p>Tidak ada pemisahan logika bisnis, data, dan presentasi.</p></li><li><p>Setiap perubahan kecil bisa merusak bagian lain.</p></li></ul><p>Dalam konteks pembahasan di atas:</p><p>Jika kita memaksa memakai <em>Transaction Script</em> atau <em>Active Record</em> untuk domain yang kompleks (seperti <em>core subdomain</em>), cepat atau lambat sistem akan jadi <em>Big Ball of Mud.</em></p><p>Kenapa? Karena fungsi-fungsi akan saling memanggil, logika duplikat di mana-mana, dan tidak ada satu model mental yang jelas tentang &#8220;bagaimana bisnis bekerja&#8221; di dalam kode.</p><h2>Active Record</h2><p>Active Record juga berasal dari buku Fowler yang sama, dan definisinya adalah:</p><blockquote><p>Definisi: &#8220;An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.&#8221;<br>&#8212; <em>Martin Fowler, P of EAA, 2003.</em></p></blockquote><p>Artinya:</p><ul><li><p>Setiap baris di tabel database direpresentasikan oleh sebuah objek.</p></li><li><p>Objek itu <em>&#8220;aktif&#8221;</em> karena bisa menyimpan (<code>save()</code>), memperbarui (<code>update()</code>), atau menghapus (<code>delete()</code>) dirinya sendiri.</p></li><li><p>Kadang juga memuat logika bisnis sederhana, seperti validasi atau penghitungan kecil.</p></li></ul><p>Analogi: seperti lembar Excel di mana tiap baris bisa langsung &#8220;menyimpan dirinya ke server&#8221; begitu kita ubah isinya.</p><p>Active Record biasanya lebih rapi dari Transaction Script karena sudah mulai ada objek dan data berelasi, tapi belum punya pemisahan yang jelas antara data dan aturan bisnis.</p><p>Pola ini diperkenalkan oleh Fowler dan disitir Khononov (2022) sebagai objek yang &#8220;membungkus satu baris di tabel database, mengenkapsulasi akses database, dan menambah logika bisnis di data tersebut&#8221;. Artinya, setiap entitas data (misalnya baris <code>User</code> di tabel) direpresentasikan oleh sebuah objek yang punya metode sendiri, termasuk operasi <em>save()</em> atau <em>update()</em> ke database. </p><p>Active Record cocok ketika logika bisnis masih sederhana, tapi struktur datanya relatif rumit (misal relasi banyak-ke-banyak). Contohnya, kalau kita punya struct Rust <code>User</code>:</p><pre><code><code>struct User {
    id: u32,
    name: String,
    email: String,
}

impl User {
    fn save(&amp;self, conn: &amp;DbConnection) {
        // Contoh sederhana: INSERT atau UPDATE ke DB
        conn.execute(&#8221;INSERT INTO users ...&#8221;, &amp;[&amp;self.name, &amp;self.email]);
    }
    fn increment_logins(&amp;mut self, conn: &amp;DbConnection) {
        self.logins += 1;
        self.save(conn);
    }
}
</code></code></pre><p>Di sini, <code>User</code> bertindak sebagai <em>active record</em>: ia menyimpan datanya (<code>id</code>, <code>name</code>, dll.) dan punya method <code>save()</code> untuk persist ke database. Jika kita perlu modifikasi data kompleks, kita manipulasi objek <code>User</code> dan panggil <code>user.save(conn)</code> untuk update. </p><p>Menurut Khononov, tujuan pola ini adalah <em>mengenkapsulasi kompleksitas pemetaan antara object ke skema database</em>. Dibanding Transaction Script, skema Active Record menyediakan objek-objek khusus yang memuat data dan operasi CRUD mereka sendiri.</p><p><strong>Kapan pakai Active Record?</strong> Beberapa poin:</p><ul><li><p>Logika masih sederhana (CRUD, validasi input ringan) tapi datanya lebih struktur.</p></li><li><p>Berguna di <em>subdomain pendukung/generik</em> yang butuh konversi data kompleks ke model aplikasi.</p></li><li><p>Intinya: Active Record adalah Transaction Script yang &#8220;hidup&#8221; &#8211; yaitu setiap operasi bisnis masih dilakukan di luar objek, tapi objek data punya <em>save()</em> sendiri. Ini punya kekurangan: logika bisnis tetap tersebar di layanan/prosedur, jadi sering disebut <em>anemic domain model</em>. Maka jangan gunakan di core subdomain yang seharusnya punya domain model penuh (<em>full domain model</em>).</p></li></ul><p>Ringkasnya, bagian ini memberikan pemahaman bahwa untuk kasus sederhana kita bisa pakai Transaction Script atau Active Record. Keduanya ringan dan cepat diimplementasi, tapi terbatas pada logika sederhana di subdomain pendukung. Untuk core subdomain dengan banyak aturan, kita akan membahas pada pola Domain Model berikutnya.</p><h3>Anemic Domain Model</h3><p>Istilah ini juga dari Martin Fowler, dan Khononov menyinggungnya saat membandingkan Active Record dengan Domain Model.</p><blockquote><p>Definisi: &#8220;Anemic Domain Model is a domain model where the business logic is absent and resides in services instead of the entities themselves.&#8221;<br>&#8212; <em>Martin Fowler, 2003.</em></p></blockquote><p>Artinya:</p><ul><li><p>Objek domain hanya menyimpan data (getter &amp; setter).</p></li><li><p>Logika bisnis tersebar di service/fungsi lain.</p></li><li><p>Secara teknis modelnya ada, tapi secara semantik &#8220;kosong&#8221;.</p></li></ul><p>Contoh dalam Rust:</p><pre><code><code>struct Order {
    id: u32,
    total: f64,
    status: String,
}

fn confirm(order: &amp;mut Order) {
    if order.total &gt; 0.0 {
        order.status = &#8220;Confirmed&#8221;.to_string();
    }
}
</code></code></pre><p>Objek <code>Order</code> di sini tidak tahu apa-apa tentang bisnisnya sendiri.<br>Segala logika berada di luar (<code>confirm()</code>). Akibatnya, aturan bisnis bisa dengan mudah tersebar dan bertentangan.</p><p>DDD menolak pola ini karena tujuan DDD adalah memusatkan logika bisnis di dalam domain model, agar kode benar-benar mencerminkan pemikiran bisnis.</p><h3>Full Domain Model</h3><p>Dalam DDD, domain model penuh, istilah aslinya adalah &#8220;Rich Domain Model&#8221; atau &#8220;Full-Fledged Domain Model&#8221;.</p><blockquote><p>Definisi: &#8220;A rich domain model is one where domain objects encapsulate both data and behavior, enforcing business rules internally.&#8221;<br>&#8212; <em>Evans, Domain-Driven Design, 2004.</em></p></blockquote><p>Bedanya dengan <em>anemic domain model berdasarkan karakteristik</em>:</p><ul><li><p>Rich (Full) Domain Model</p><ul><li><p>Data dan perilaku: Digabung di entitas.</p></li><li><p>Aturan Bisnis: Ditegakkan di dalam entitas.</p></li><li><p>Keterwakilan domain: Kuat, selaras dengan bahasa bisnis.</p></li><li><p>Cocok untuk: Core subdomain.</p></li></ul></li><li><p>Anemic Domain Model</p><ul><li><p>Data dan perilaku: Terpisah.</p></li><li><p>Aturan Bisnis: Tersebar di service luar.</p></li><li><p>Keterwakilan domain: Lemah, cenderung CRUD.</p></li><li><p>Cocok untuk: Supporting/generic subdomain.</p></li></ul></li></ul><p>Jadi ketika Khononov menulis bahwa &#8220;core subdomain seharusnya memiliki <em>domain model penuh</em>&#8221;, maksudnya adalah:</p><p>Subdomain yang menjadi keunggulan utama bisnis harus diimplementasikan dengan <em>rich domain model</em>, agar aturan bisnis dan konsep bisnis benar-benar hidup di dalam kode, bukan di spreadsheet, dokumen, atau service-service longgar.</p><h3>Domain Model Berdasarkan Pola yang Cocok</h3><p>Ada spektrum kompleksitas yang mempengaruhi pemilihan domain model yang cocok:</p><ul><li><p>Kondisi domain sangat sederhana (ETL, batch job, CRUD data referensi)</p><ul><li><p>Pola yang cocok: Transaction Script.</p></li><li><p>Karena tidak perlu model atau logika kompleks.</p></li></ul></li><li><p>Kondisi domain sederhana tapi punya struktur data berelasi</p><ul><li><p>Pola yang cocok: Active Record.</p></li><li><p>Karena sedikit OO, tapi mudah dan cepat.</p></li></ul></li><li><p>Kompleks dengan aturan bisnis yang dinamis</p><ul><li><p>Pola yang cocok: Rich Domain Model.</p></li><li><p>Karena logika terpusat di entitas &amp; aggregate.</p></li></ul></li><li><p>Butuh audit / histori</p><ul><li><p>Pola yang cocok: Event-Sourced Domain Model.</p></li><li><p>Karena Domain Model + Event Sourcing.</p></li></ul></li></ul><h2>Melihat Kembali Subdomain Pendukung (supporting subdomain)</h2><p>Di atas banyak dibahas bahwa keduanya terbatas pada logika sederhana di subdomain pendukung. Kita lihat kembali klasifikasi subdomain pada DDD (Khononov, 2022):</p><ul><li><p>Core Subdomain</p><ul><li><p>Karakteristik: Menjadi sumber keunggulan kompetitif bisnis. Kompleks, sering berubah, butuh inovasi tinggi.</p></li><li><p>Fokus solusi: Perlu desain DDD mendalam, domain model penuh, investasi besar.</p></li></ul></li><li><p>Supporting Subdomain</p><ul><li><p>Karakteristik: Mendukung operasional inti, tapi tidak membedakan bisnis dari kompetitor. Biasanya sederhana.</p></li><li><p>Fokus solusi: Gunakan solusi pragmatis (Transaction Script, Active Record, atau framework siap pakai)</p></li></ul></li><li><p>Generic Subdomain</p><ul><li><p>Karakteristik: Umum dipakai semua bisnis (contoh: autentikasi, log aktivitas).</p></li><li><p>Fokus solusi: Lebih baik dibeli atau pakai library standar.</p></li></ul></li></ul><p>Sederhananya:</p><ul><li><p><em>Supporting subdomain</em> masih penting untuk bisnis, tapi tidak menentukan keberhasilan utama.</p></li><li><p>Karena kompleksitasnya rendah dan nilai strategisnya kecil, maka kita tidak perlu investasi arsitektur rumit seperti Domain Model penuh.</p></li><li><p>Inilah kenapa <em>Transaction Script</em> dan <em>Active Record</em> cocok: cepat dibuat, mudah dipelihara, cukup stabil.</p></li></ul><p>Sebaliknya, <em>core subdomain</em> biasanya punya banyak aturan bisnis, ketergantungan lintas fungsi, dan terus berubah.</p><h3>Data &amp; Logika Bisnis</h3><p>Pernyataan &#8220;pemisahan antara data dan logika bisnis&#8220; ini sering muncul dalam konteks arsitektur software, misalnya <em>Separation of Concerns</em>.</p><p>Artinya: Data (apa yang disimpan) dan logika bisnis (apa yang dilakukan terhadap data itu) tidak seharusnya bercampur dalam satu tempat.</p><p>Contoh salah:</p><pre><code><code>fn save_order_to_db(order_id: u32, total: f64) {
    // ... query ke DB ...
    if total &gt; 1000000.0 {
        // logika bisnis diselipkan di sini
        println!(&#8221;Diskon 10%&#8221;);
    }
}
</code></code></pre><p>Contoh benar:</p><pre><code><code>struct Order {
    id: u32,
    total: f64,
}

impl Order {
    fn apply_discount(&amp;mut self) {
        if self.total &gt; 1000000.0 {
            self.total *= 0.9;
        }
    }
}

fn save_order_to_db(order: &amp;Order) {
    // hanya urusan penyimpanan
}
</code></code></pre><p>Pada contoh benar, fungsi <code>save_order_to_db()</code> hanya fokus pada <strong>data persistence</strong>, sedangkan <code>apply_discount()</code> berisi <strong>logika bisnis</strong>.<br>Keduanya terpisah untuk memudahkan pengujian, refaktor, dan perubahan aturan bisnis tanpa merusak cara penyimpanan data.</p><p>Pemisahan antara data, logika bisnis, dan presentasi adalah prinsip dasar arsitektur aplikasi, sering disebut sebagai <strong>three-layer (or three-tier) architecture</strong>.</p><ul><li><p>Presentation layer</p><ul><li><p>Tugas utama: Menampilkan data kepada pengguna dan menerima input.</p></li><li><p>Contoh dalam aplikasi: Antarmuka pengguna (UI), web page, REST API endpoint, CLI.</p></li></ul></li><li><p>Business Logic layer</p><ul><li><p>Tugas utama: Menjalankan aturan dan keputusan bisnis.</p></li><li><p>Contoh dalam aplikasi: Fungsi domain, service, entitas, aggregate.</p></li></ul></li><li><p>Data Access layer atau Persistence Layer</p><ul><li><p>Tugas utama: menyimpan dan mengambil data.</p></li><li><p>Contoh dalam aplikasi: Database, ORM, repository.</p></li></ul></li></ul><p>Dalam konteks arsitektur, &#8220;presentation layer&#8221; mencakup <em>segala sesuatu yang berhubungan dengan interaksi pengguna atau sistem lain. </em>Misalnya:</p><ul><li><p>UI web atau mobile,</p></li><li><p>API endpoint (yang melayani HTTP request),</p></li><li><p>atau bahkan CLI untuk admin.</p></li></ul><p>Presentasi <em>tidak boleh</em> tahu detail logika bisnis, cukup memanggil fungsinya saja.<br>Contoh:</p><pre><code><code>// presentation layer
fn handle_checkout_request(user_input: CheckoutData) {
    let mut order = Order::new(user_input.items);
    order.apply_discount(); // business logic
    repository::save(order); // data layer
}
</code></code></pre><p>Ketiganya punya tanggung jawab berbeda:</p><ul><li><p>Presentation layer: berbicara dengan pengguna atau sistem lain.</p></li><li><p>Business logic layer: memutuskan apa yang boleh atau harus terjadi.</p></li><li><p>Data layer: mengelola penyimpanan (database, cache, dsb).</p></li></ul><p>Prinsip ini disebut <strong>Separation of Concerns</strong>: memisahkan tanggung jawab agar sistem lebih modular dan mudah berkembang.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Mengintegrasikan Bounded Contexts]]></title><description><![CDATA[Meski disebut bounded, konteks-konteks yang berbeda, meskipun penyebutannya, tidak boleh jalan sendiri-sendiri: mereka harus saling berinteraksi untuk mencapai tujuan sistem secara keseluruhan.]]></description><link>https://www.0-1.my.id/p/mengintegrasikan-bounded-contexts</link><guid isPermaLink="false">https://www.0-1.my.id/p/mengintegrasikan-bounded-contexts</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Mon, 13 Oct 2025 15:21:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!VNtl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Meski disebut <em>bounded</em>, konteks-konteks yang berbeda, meskipun penyebutannya, tidak boleh jalan sendiri-sendiri: mereka harus <strong>saling berinteraksi</strong> untuk mencapai tujuan sistem secara keseluruhan. Interaksi itu diwujudkan lewat <em>kontrak</em>, titik temu di mana satu konteks menggunakan output dari konteks lain. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VNtl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VNtl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VNtl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VNtl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!VNtl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2dee6ab-30d1-4c9f-8448-e398450ff5e8_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mengintegrasikan Bounded Contexts.</figcaption></figure></div><p>Tergantung pada hubungan tim pengembangnya, DDD mengenalkan beberapa pola integrasi bounded context:</p><ul><li><p><strong>Partnership</strong> (Kerjasama Dua Arah): Dua tim berkolaborasi erat, saling bantu menyesuaikan antarmuka jika dibutuhkan. Tidak ada pihak yang memaksakan modelnya; setiap perubahan disepakati atau dinegosiasikan bersama. Pola ini memerlukan komunikasi intensif dan mungkin <em>Continuous Integration</em> agar tiap perubahan cepat diuji bersama.</p></li><li><p><strong>Shared Kernel</strong>: Dua atau lebih bounded context berbagi sebagian model yang sama (misalnya model otorisasi pengguna). Perubahan di bagian bersama (kernel) langsung memengaruhi semua konteks. Oleh karena itu, hanya fitur inti yang benar-benar perlu yang sebaiknya digabungkan di sini, biasanya berupa kontrak integrasi atau struktur data bersama. Untuk implementasi, kode bersama bisa diletakkan di satu modul yang di-<em>link</em> oleh setiap konteks. Setiap perubahan mesti diuji secara lintas-konteks agar tidak ada yang rusak.</p></li></ul><p>Kelompok berikutnya adalah <strong>Customer&#8211;Supplier</strong>, hubungan satu arah dengan tim penyuplai (supplier) dan tim pelanggan (customer):</p><ul><li><p><strong>Conformist</strong>: Tim supplier mendikte modelnya dan tim pelanggan <em>mengikuti begitu saja</em>. Misalnya, jika API yang disediakan rekanan sudah baku, tim kita mungkin cuma mengonsumsi mentah-mentah data itu tanpa negosiasi. Pola ini tidak memerlukan adaptasi besar; tim pelanggan menerima persyaratan supplier seperti adanya. Biasanya cocok untuk model standar industri yang <em>cukup baik</em> dan tidak ingin diubah.</p></li><li><p><strong>Anticorruption Layer (ACL)</strong>, Jika tim supplier <em>berkuasa penuh</em>, tetapi modelnya tidak cocok atau sering berubah (misal sistem warisan dengan schema kacau), tim pelanggan bisa membuat lapisan perantara (translator) yang menerjemahkan model supplier ke model sendiri. Misalnya, jika subdomain kita termasuk inti yang rumit, kita tidak mau ikut-ikutan merusak modelnya. Atau jika kontrak sering berubah, ACL menjaga agar perubahan itu hanya mengganggu translator, bukan seluruh sistemnya. Intinya, ACL <em>mengisolasi</em> konteks kita dari istilah asing dan membuat model kita lebih bersih sesuai kebutuhan.</p></li><li><p><strong>Open-Host Service</strong>: Kebalikan dari ACL, di sini supplier <em>melindungi</em> pelanggannya. Supplier membuat model publik (<em>published language</em>) yang nyaman bagi konsumen, lalu menjembatani model internalnya ke model publik tersebut. Dengan begitu, supplier dapat mengubah model internalnya tanpa mengganggu konsumen, asalkan masih menerjemahkannya ke bahasa publik yang sudah ditetapkan. Pola ini sering digunakan jika supplier ingin memberi layanan yang stabil bagi banyak konsumen sekaligus.</p></li></ul><p>Terakhir, ada pola <strong>Separate Ways</strong>, dua tim memutuskan <em>tidak berkolaborasi sama sekali</em>. Ini bukan ideal, tapi bisa terjadi karena berbagai alasan. Misalnya, jika komunikasi antar tim sangat sulit (pemisahan geografis atau politik internal), lebih murah menyalin fungsionalitas di kedua sisi daripada memaksakan integrasi. Atau jika yang ingin dibagikan adalah subdomain <em>generik</em> (seperti logging, notifikasi, dll), mungkin lebih simpel setiap tim melokalkan solusinya sendiri daripada bikin satu layanan terpusat. Juga, jika model di kedua sisi benar-benar berbeda sehingga ACL atau Conformist menjadi mahal atau tidak mungkin, tim bisa memilih Duplicate (Separate Ways). <br><strong>Peringatan:</strong> pola ini <strong>tidak boleh</strong> dipakai untuk subdomain inti perusahaan, karena menyalin inti bisnis berarti merugi, kita kehilangan optimasi dan konsistensi yang seharusnya menjadi sumber keunggulan.</p><p>Setelah semua hubungan integrasi ini terdefinisi, kita dapat menggambarnya dalam <strong>context map</strong>, peta visual bounded context beserta tipe integrasi antaranya. Context map ini memberikan wawasan strategis tinggi: apa saja komponen besar sistem, siapa bermitra dengan siapa, siapa yang mandiri atau bahkan memisahkan diri, dan pola komunikasi seperti apa yang terjadi antar tim. <br>Misalnya, sebuah panah &#8216;anticorruption layer&#8217; dari tim A ke B menunjukkan tim A memakai ACL terhadap tim B. Context map sebaiknya disusun sejak awal proyek dan terus diperbarui bersama tim &#8211; misalnya setiap tim bertanggung jawab menjaga gambaran integrasi kontekstualnya tetap up-to-date.</p><p>Diulang kembali secara singkat, berikut pola-pola utama integrasi bounded context dalam DDD (Khononov, 2022):</p><ul><li><p><strong>Partnership:</strong> Integrasi ad hoc dengan komunikasi dua arah.</p></li><li><p><strong>Shared Kernel:</strong> Dua konteks berbagi potongan model yang konsisten.</p></li><li><p><strong>Conformist:</strong> Konsumen <em>menyesuaikan diri</em> dengan model penyedia layanan.</p></li><li><p><strong>Anticorruption Layer:</strong> Konsumen membuat lapisan penerjemah agar model penyedia tidak merusak model internalnya.</p></li><li><p><strong>Open-Host Service:</strong> Penyedia menyiapkan antarmuka publik agar konsumennya nyaman, sementara detail internal tetap fleksibel.</p></li><li><p><strong>Separate Ways:</strong> Dua tim bekerja terpisah, setiap konteks menduplikasi kebutuhan umum agar integrasi tidak diperlukan.</p></li></ul><p>Peta konteks (<em>context map</em>) menggambarkan semua ini secara keseluruhan. Dengan memahami pola-pola integrasi ini, kita dapat menyelaraskan desain teknis dengan struktur organisasi dan strategi bisnis yang ada.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p>]]></content:encoded></item><item><title><![CDATA[Mengatasi Kompleksitas Domain dengan Bounded Contexts]]></title><description><![CDATA[Setelah memiliki bahasa yang sama, dengan Ubiquitous language, kita menyadari bahwa dalam satu perusahaan bisa jadi ada beberapa model untuk hal yang sama.]]></description><link>https://www.0-1.my.id/p/mengatasi-kompleksitas-domain-dengan-bounded-contexts</link><guid isPermaLink="false">https://www.0-1.my.id/p/mengatasi-kompleksitas-domain-dengan-bounded-contexts</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sun, 12 Oct 2025 15:20:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!r-Ah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setelah memiliki bahasa yang sama, dengan Ubiquitous language, kita menyadari bahwa dalam satu perusahaan bisa jadi ada <em>beberapa</em> model untuk hal yang sama. Ahli domain dari divisi berbeda mungkin punya definisi berbeda terhadap suatu konsep. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!r-Ah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!r-Ah!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!r-Ah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!r-Ah!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!r-Ah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e3235a7-bef2-44f5-8e28-6de2d8a587e3_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Mengatasi Kompleksitas Domain dengan Bounded Contexts.</figcaption></figure></div><p>Contohnya dari buku Khononov (2022): perusahaan telemarketing; tim <strong>marketing</strong> memandang <em>&#8220;lead&#8221;</em> sebagai sekadar notifikasi ketika seorang prospek menunjukkan minat. Tapi tim <strong>sales</strong> melihat <em>&#8220;lead&#8221;</em> sebagai proses penjualan yang lengkap, dari awal sampai konversi &#8211; sebuah entitas yang jauh lebih kompleks.</p><p>Masalahnya, jika kita mencoba membuat <strong>satu model tunggal</strong> 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 &#8220;marketingLead&#8221; dan &#8220;salesLead&#8221; tidak membantu banyak karena tetap membingungkan pemakai bahasa (orang cenderung tidak pakai istilah seperti itu dalam obrolan sehari-hari).</p><p>Solusi DDD-nya adalah <strong>Bounded Context</strong>: kita memecah bahasa umum tadi menjadi beberapa bahasa yang lebih kecil, masing-masing dipakai dalam konteks tertentu. </p><p>Secara harfiah, &#8220;bounded context&#8221; berarti &#8220;konteks yang memiliki batas.&#8221;<br>Kata <em>bounded</em> artinya &#8220;dibatasi,&#8221; dan <em>context</em> artinya &#8220;lingkungan makna&#8221; atau &#8220;tempat di mana istilah-istilah punya arti tertentu.&#8221;</p><p>Dalam konteks DDD, Bounded Context adalah batas eksplisit di mana satu model domain dan bahasa umum (ubiquitous language) berlaku secara konsisten.<br>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.</p><p>Dalam contoh tadi, kita bisa punya dua bounded context: <strong>Marketing</strong> dan <strong>Sales</strong>. Di tiap konteks ini, istilah <em>&#8220;Lead&#8221;</em> hanya punya satu arti saja sesuai kebutuhan konteks itu. Dengan cara ini, tidak ada kebingungan di dalam kode &#8211; misalnya <code>marketing::Lead</code> bisa kita definisikan terpisah dari <code>sales::Lead</code> dalam kode Rust:</p><pre><code><code>mod marketing {
    #[derive(Debug)]
    struct Lead {
        contact_info: String,
        // ...
    }
}
mod sales {
    #[derive(Debug)]
    struct Lead {
        customer_id: u32,
        // ...
    }
}
</code></code></pre><p>Dengan model seperti di atas, <code>marketing::Lead</code> dan <code>sales::Lead</code> mengandung arti berbeda meski namanya sama. Ini menggambarkan bounded context: setiap modul atau bagian sistem memiliki <strong>bahasanya sendiri</strong> yang konsisten di dalam konteksnya. Lalu, kapan kita berhenti memecah konteks? Sama seperti <em>peta</em>, tiap model punya batas manfaatnya. Bounded context adalah batas pemakaiannya: setiap model hanya <strong>berguna dalam domain masalah yang spesifik</strong>. Peta jalan tidak bisa dipakai di laut; begitupun model &#8220;Lead&#8221; marketing tidak berguna untuk logika sales.</p><p>DDD mengajarkan bahwa <strong>kejelasan makna lebih penting daripada keseragaman istilah</strong>.<br>Dengan bounded context:</p><ul><li><p>Tim bisa bekerja secara independen,</p></li><li><p>Model mereka tetap konsisten di dalam konteksnya,</p></li><li><p>Dan integrasi antar konteks bisa diatur lewat pola yang eksplisit (seperti <em>Shared Kernel</em> atau <em>Anticorruption Layer</em>), yang akan dibahas selanjutnya.</p></li></ul><p>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 &#8211; bikin repot!</p><p>Perbedaan <strong>subdomain</strong> (yang dibahas di artikel <a href="https://www.0-1.my.id/p/memahami-domain-bisnis-pada-ddd">memahami domain bisnis</a>) dengan <strong>bounded context</strong> penting disini. Subdomain berasal dari analisis bisnis (sesuai strategi perusahaan), sedangkan bounded context kita <em>rancang</em> 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.</p><p>Selain sebagai batas konsep, bounded context juga menjadi <strong>batas fisik dan kepemilikan</strong> 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.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Komunikasi dengan Ubiquitous Language]]></title><description><![CDATA[Setelah tahu apa bisnisnya, kita perlu memahami bagaimana bisnis itu berjalan di level operasional. Bagian ini membawa kita memahami konsep bahasa umum (ubiquitous language) DDD untuk komunikasi.]]></description><link>https://www.0-1.my.id/p/komunikasi-dengan-ubiquitous-language</link><guid isPermaLink="false">https://www.0-1.my.id/p/komunikasi-dengan-ubiquitous-language</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Sat, 11 Oct 2025 16:34:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xAVt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setelah tahu <em>apa</em> bisnisnya, kita perlu memahami <em>bagaimana</em> bisnis itu berjalan di level operasional. Bagian ini membawa kita memahami konsep <strong>bahasa umum (ubiquitous language)</strong> DDD untuk komunikasi dan penemuan pengetahuan domain. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xAVt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xAVt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xAVt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:263350,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.0-1.my.id/i/175894259?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xAVt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xAVt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe17b1bd6-489d-44c0-80c3-401a61ed275b_1024x1024.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Komunikasi dengan Ubiquitous Language.</figcaption></figure></div><p>Pengetahuan domain (<em>domain knowledge</em>) adalah semua pemahaman tentang dunia nyata yang sedang kita coba pecahkan lewat sistem/<em>software</em> yang kita bangun. Sistem/<em>software</em> adalah representasi digital dari realitas bisnis. Karena itu dalam DDD, langkah pertama adalah menemukan atau menggali pengetahuan domain, supaya tim engineering dan bisnis punya pemahaman yang sama tentang apa yang sebenarnya ingin diselesaikan.</p><p>Intinya, setiap kali kita mengembangkan sistem perangkat lunak, kita sebenarnya memecahkan masalah bisnis yang dihadapi perusahaan (misalnya, mengoptimalkan pengiriman paket FedEx atau melacak stok toko). Masalah bisnis ini rumit dan biasanya hanya diketahui oleh para ahli domain. Jika kita tidak bisa menggunakan istilah mereka, kita akan mudah salah paham tentang kebutuhan sistem.</p><p>Masalah umum dalam proyek pengembangan adalah <strong>hambatan komunikasi</strong>. Pengetahuan domain sering &#8220;diterjemahkan&#8221; berkali-kali: dari ahli domain (<em>domain expert</em>) ke analis, lalu ke dokumen syarat, lalu ke desain sistem, lalu ke kode program. Setiap penerjemahan seperti permainan <em>bisik-bisikan</em>: informasi penting bisa hilang atau bias. Akibatnya, tim developer bisa saja membangun <em>solusi yang salah</em> karena tidak sepenuhnya memahami masalah aslinya.</p><p>Ahli domain (domain expert) adalah orang yang benar-benar <em>paham seluk-beluk dunia nyata yang sedang kita pecahkan lewat sistem/software</em>. Mereka tidak harus bisa coding, tapi mereka tahu <em>kenapa sesuatu harus dilakukan seperti itu</em> dalam bisnis.</p><p>Untuk menghindari informasi penting yang hilang atau bias, DDD memperkenalkan konsep <em><strong>Ubiquitous Language</strong></em>, satu set istilah tunggal yang digunakan oleh semua pihak (pengembang, analis, ahli domain, bahkan UI/UX) ketika membicarakan domain bisnis. Artinya, jangan lagi menggunakan jargon teknis di antara ahli bisnis (<em>business expert</em>). Gunakan hanya istilah bisnis yang mudah dipahami semua orang. Misalnya, ketika merancang sistem manajemen kampanye iklan, semua orang harus sepakat pada frase seperti <em>&#8220;kampanye&#8221;</em>, <em>&#8220;materi iklan&#8221;</em>, <em>&#8220;tayang&#8221;</em>, bukan <em>&#8220;iframe&#8221;</em>, <em>&#8220;record SQL&#8221;</em> atau istilah IT lainnya yang mungkin tidak dipahami pihak bisnis.</p><p>Fase <em>penemuan pengetahuan domain</em> terjadi lewat <strong>kolaborasi aktif antara engineer, ahli domain, dan ahli bisnis</strong>.<br>Tujuannya bukan cuma mengumpulkan requirement, tapi menyatukan cara berpikir tentang masalah dan solusinya.</p><ul><li><p>Ahli bisnis membawa <em>visi dan prioritas</em> (&#8220;kita ingin menurunkan waktu pengiriman&#8221;).</p></li><li><p>Ahli domain menjelaskan <em>realitas dan batasan teknis di lapangan</em> (&#8220;kalau hujan, kurir butuh rute alternatif&#8221;).</p></li><li><p>Engineer menerjemahkan semua itu menjadi <em>model domain</em> dan <em>bahasa umum</em> yang bisa diimplementasikan di software.</p></li></ul><p>Dengan analogi:</p><blockquote><p>Ahli bisnis membantu <em>menentukan arah perahu</em>, ahli domain membantu <em>menavigasi jalur aman</em>, dan engineer membantu <em>membangun perahunya</em>.</p></blockquote><p><em>Ubiquitous Language</em> harus <strong>konsisten dan tepat</strong>. Setiap istilah harus punya satu arti yang jelas, tidak boleh ambigu atau punya sinonim ganda. Misalnya, jika di bisnis asuransi kata <em>&#8220;polis&#8221;</em> bisa berarti aturan regulasi atau kontrak asuransi, dalam bahasa umum kita harus meluruskannya menjadi dua istilah terpisah: <em>&#8220;peraturan regulasi&#8221;</em> dan <em>&#8220;kontrak asuransi&#8221;</em>. Begitu juga kita sebaiknya tidak mencampur istilah seperti <em>&#8220;user&#8221;</em>, <em>&#8220;visitor&#8221;</em>, dan <em>&#8220;account&#8221;</em> jika ternyata memiliki makna berbeda dalam bisnis, setiap istilah harus dipakai secara khusus sesuai konteks. Dengan begitu, tidak ada salah paham antar tim.</p><p>Secara keseluruhan, kita sebenarnya sedang membuat model domain bisnis menggunakan bahasa umum itu. Model di sini diibaratkan seperti <em>peta</em>: kita tidak menggambar semua detail bumi, hanya memilih aspek yang relevan untuk tujuan tertentu (misalnya peta jalan, peta metro, atau peta cuaca). Begitu pula model sistem. Contohnya, untuk sistem kampanye iklan, kita mungkin butuh entitas <code>Campaign</code> dengan field seperti <code>id</code>, <code>is_published</code>, dan daftar <code>placements</code>. Dalam kode Rust, misalnya:</p><pre><code><code>struct Campaign {
    id: u32,
    title: String,
    placements: Vec&lt;Placement&gt;,
    is_published: bool,
    // field lainnya sesuai kebutuhan bisnis...
}
</code></code></pre><p><strong>Model domain</strong> (<em>domain model</em>) adalah <strong>representasi mental dari bagaimana dunia bisnis bekerja</strong>, yang kita tuangkan ke dalam bentuk istilah, diagram, dan akhirnya kode. Model domain bukan sekadar diagram UML atau ERD, melainkan gabungan dari konsep, relasi, dan aturan bisnis yang disepakati oleh tim.<br>Contoh lainnya dalam sistem e-commerce:</p><ul><li><p>Entitas: <code>Order</code>, <code>Product</code>, <code>Customer</code>, <code>Payment</code></p></li><li><p>Relasi: <code>Order</code> berisi beberapa <code>Product</code>, dan terhubung dengan satu <code>Customer</code></p></li><li><p>Aturan bisnis: <code>Order</code> tidak bisa dikonfirmasi jika <code>Payment</code> belum berhasil</p></li></ul><p>Model domain adalah <strong>jantung DDD</strong>, karena semua keputusan desain dan kode mengacu ke sana.</p><p><em><strong>Ubiquitous language</strong></em> adalah <strong>kosakata yang disepakati bersama</strong> oleh semua pihak (developer, ahli domain, manajer, tester) untuk membicarakan hal-hal di dalam model domain.</p><ul><li><p>Kalau model domain berisi <em>konsep dan relasi</em>,<br>maka <em>bahasa umum</em> adalah kata-kata yang dipakai untuk menyebut konsep-konsep itu.</p></li><li><p>Bahasa umum harus muncul di percakapan, dokumentasi, <em>dan</em> kode.</p></li></ul><p>Contoh:</p><ul><li><p>Kalau di bisnis disebut &#8220;pesanan dikonfirmasi&#8221;, maka di kode pun sebaiknya ada <code>order.confirm()</code> &#8212; bukan <code>flag = true</code> atau <code>set_status(1)</code>.</p></li><li><p>Kalau ahli domain menyebut &#8220;pengiriman gagal karena kurir kehabisan slot&#8221;, maka model domain perlu entitas <code>CourierSchedule</code>, bukan sekadar <code>delivery_attempts</code>.</p></li></ul><p>Dengan begitu, software benar-benar mencerminkan cara berpikir orang bisnis, bukan sekadar logika teknis.</p><p>Dengan analogi:</p><blockquote><p>Bayangkan kamu main &#8220;pesan berantai&#8221; di masa kecil, seseorang berbisik ke orang kedua, lalu diteruskan ke orang ketiga, dan seterusnya. Di akhir, pesan sering berubah total dari yang aslinya.</p></blockquote><p>Nah, dalam proyek software tradisional:</p><ol><li><p>Ahli domain (<em>domain expert</em>) menjelaskan masalah ke analis bisnis.</p></li><li><p>Analis menulis dokumen requirement.</p></li><li><p>Dokumen itu dibaca arsitek atau developer.</p></li><li><p>Developer menulis kode berdasarkan interpretasinya.</p></li></ol><p>Di setiap tahap, arti bisa melenceng sedikit demi sedikit.<br>Hasil akhirnya: software yang <em>secara teknis benar</em> tapi <em>secara bisnis bisa salah</em>.</p><p>Dengan DDD, kita <em>memotong rantai itu</em>: developer bicara langsung dengan ahli domain, memakai <em>bahasa umum yang sama</em>, sehingga model yang tertulis di kode benar-benar mewakili pemahaman bisnis yang sebenarnya. Hasilnya, pengembang dapat membuat kode (dan model data) yang <em>betul-betul</em> sesuai dengan pemikiran dan kebutuhan bisnis, sehingga sedikit konflik ketika kebutuhan berubah.</p><p><strong>Model data</strong> biasanya berarti <em>struktur penyimpanan</em>, tabel di database, kolom, tipe data, relasi. Fokusnya: bagaimana data disimpan dan diakses secara efisien.<br>Contohnya:</p><pre><code><code>struct OrderRow {
    id: i64,
    customer_id: i64,
    status_code: i32,
    created_at: DateTime&lt;Utc&gt;,
}
</code></code></pre><p>Sedangkan <strong>model domain</strong> berfokus pada <em>logika dan aturan bisnis</em>, bagaimana entitas berperilaku dan saling berinteraksi.<br>Contohnya:</p><pre><code><code>struct Order {
    id: OrderId,
    customer: CustomerId,
    items: Vec&lt;OrderItem&gt;,
    status: OrderStatus,
}

impl Order {
    fn confirm(&amp;mut self) -&gt; Result&lt;(), &amp;&#8217;static str&gt; {
        if self.items.is_empty() {
            Err(&#8221;order must have items before confirmation&#8221;)
        } else {
            self.status = OrderStatus::Confirmed;
            Ok(())
        }
    }
}
</code></code></pre><p>Dalam DDD, <strong>model domain</strong> adalah pusatnya, sedangkan model data hanyalah <em>salah satu cara</em> menyimpan informasi dari model domain.<br>Jadi, relasi antara keduanya seperti: &#8220;Model domain menjelaskan makna bisnisnya, model data menyimpan faktanya.&#8221;</p><p>Kalo mau tahu lebih jauh mengenai pemrograman Rust bisa belajar di kelas <a href="https://www.dicoding.com/academies/881">Belajar Pemrograman Rust untuk Pemula</a> di Dicoding.</p><h2><strong>Referensi</strong></h2><p>Khononov, V. (2022). <em>Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy</em>. O&#8217;Reilly Media.</p>]]></content:encoded></item><item><title><![CDATA[Memahami Domain Bisnis pada DDD]]></title><description><![CDATA[Domain bisnis (business domain) adalah area utama aktivitas perusahaan, layanan atau produk yang disediakan kepada pelanggan.]]></description><link>https://www.0-1.my.id/p/memahami-domain-bisnis-pada-ddd</link><guid isPermaLink="false">https://www.0-1.my.id/p/memahami-domain-bisnis-pada-ddd</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Fri, 10 Oct 2025 15:46:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iNoM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Menulis kode yang bagus saja belum cukup untuk menghasilkan solusi yang efektif. Menurut Khononov (2022) kita harus terlebih dahulu memahami strategi bisnis perusahaan dan nilai apa yang ingin dicapai dengan perangkat lunak tersebut. Domain bisnis (<strong>business domain</strong>) adalah area utama aktivitas perusahaan, layanan atau produk yang disediakan kepada pelanggan. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iNoM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iNoM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iNoM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iNoM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!iNoM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd792ccf6-4212-464a-a214-2ebdb5961805_1024x608.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Memahami Domain Bisnis pada DDD.</figcaption></figure></div><p>Misalnya, FedEx bergerak di domain pengiriman paket, Starbucks di domain kopi, sedangkan Amazon bisa punya beberapa domain (ritel dan komputasi awan). Perusahaan juga bisa berpindah domain bisnis seiring waktu (Nokia dulu berbisnis kayu, karet, lalu telekomunikasi).</p><p>Untuk mencapai tujuan bisnisnya, sebuah perusahaan membagi pekerjaannya ke dalam subdomain yang lebih kecil. Subdomain adalah area kegiatan bisnis yang lebih terperinci, bagian dari keseluruhan domain perusahaan. Tiap subdomain saling berinteraksi agar perusahaan dapat berhasil, misalnya Starbuck tidak hanya membuat kopi (subdomain kopi), tapi juga harus mengelola lokasi gerai, pegawai, dan keuangan (subdomain pendukung) agar bisnisnya lancar.</p><p><strong>Domain-driven design</strong> (DDD) membedakan tiga jenis subdomain berdasarkan nilai strategisnya:</p><h2>Subdomain Inti (Core)</h2><p>Ini adalah hal-hal yang membuat perusahaan berbeda dari kompetitor. Subdomain inti mengandung keahlian khusus atau inovasi bisnis. Contohnya, Uber mempelopori ridesharing, atau algoritma pencarian Google yang unggul. Model bisnis inti biasanya kompleks dan sulit ditiru, karena di situlah perusahaan meraih keunggulan kompetitif.</p><h2>Subdomain Generik (Generic)</h2><p>Ini adalah aktivitas bisnis yang semua perusahaan serupa juga lakukan, dengan cara yang sama. Karena tidak memberi keunggulan khusus, perusahaan biasanya memakai solusi siap pakai. Misalnya, hampir semua sistem perlu autentikasi pengguna, lebih murah dan aman pakai implementasi umum daripada menciptakan sendiri.</p><h2>Subdomain Pendukung (Supporting)</h2><p>Ini subdomain yang penting bagi operasional tetapi tidak memberi keunggulan kompetitif. Misalnya, perusahaan periklanan online perlu katalog kreatif materi iklan. Mengelola katalog ini adalah subdomain pendukung: perlu dilakukan tetapi tidak perlu inovasi khusus karena tidak menambah keuntungan unik. Subdomain pendukung biasanya relatif sederhana (biasa berupa operasi CRUD atau ETL) dan mudah di-copy oleh pesaing tanpa merusak posisi bisnis.</p><p>Secara singkat, hanya subdomain inti yang memberikan nilai bisnis khusus (keunggulan kompetitif), sementara subdomain generik dan pendukung cenderung biasa-biasa saja. Akibatnya, perusahaan sering memprioritaskan investasi pada sistem dan inovasi di subdomain inti.</p><p>Orang-orang pakar domain (<strong>domain experts</strong>) adalah kunci di sini. Mereka adalah orang yang benar-benar memahami seluk-beluk bisnis, bukan para insinyur. Mereka bisa saja berasal dari manajemen, analis keuangan, atau pengguna akhir sistem, siapa saja yang tahu bisnis paling dalam. Tugas kita sebagai pengembang adalah menyerap ilmu dari mereka. Kita tidak dapat menjadi ahli domain sepenuhnya, tetapi kita harus menggunakan bahasa dan istilah yang mereka pakai agar solusi kita sesuai dengan kebutuhan nyata.</p><p>Ilustrasi Analogi: Anggap subdomain seperti bahan penyusun bangunan. Jika arsitek rumah fokus pada desain eksterior (core), urusan listrik, pipa, dan interior adalah supporting, sementara material bangunan standar (beton, baja) dianggap generic. Semua diperlukan, tapi kita akan bersusah payah mengubah desain eksterior daripada mengganti mutu semen yang digunakan semua orang.</p><p>Pada akhirnya, keseluruhan domain bisnis menentukan apa yang ingin dicapai perusahaan, sedangkan jenis-jenis subdomain menentukan bagaimana cara mencapainya. Memahami perbedaan ini sangat penting: dengan mengidentifikasi subdomain inti/generic/pendukung, kita bisa fokus merancang sistem yang tepat untuk tiap kasus.</p><h2>Referensi</h2><p>Konsep-konsep di atas diuraikan oleh Khononov (2022) dalam <strong>Learning Domain-Driven Design</strong>.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Mengimplementasikan Konsensus Raft untuk Database Terdistribusi ]]></title><description><![CDATA[Kita akan membangun satu atau lebih node Raft dari awal.]]></description><link>https://www.0-1.my.id/p/mengimplementasikan-konsensus-raft</link><guid isPermaLink="false">https://www.0-1.my.id/p/mengimplementasikan-konsensus-raft</guid><dc:creator><![CDATA[oon arfiandwi]]></dc:creator><pubDate>Thu, 09 Oct 2025 15:50:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rOdU!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30b13e4e-634e-4bdd-b95d-174c866b2405_256x256.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kita akan membangun satu atau lebih node Raft dari awal.</p>]]></content:encoded></item></channel></rss>