Desain Berbasis Domain dan interaksi Lintas Domain

10

Saya seorang pemula DDD relatif, tetapi saya membaca apa saja dan semua yang saya bisa dapatkan untuk mendidih dan menyaring pengetahuan saya.

Saya menemukan pertanyaan DDD ini, dan salah satu jawabannya membuat saya tertarik.

Konteks & Domain Terbatas DDD?

Dalam salah satu jawaban, poster memberikan contoh sistem e-niaga dengan produk berada di setidaknya 2 domain:

1) Katalog Produk 2) Manajemen Persediaan

OK, itu semua masuk akal, yaitu di ujung depan e-commerce Anda, Anda tertarik untuk menampilkan informasi produk, dan tidak tertarik pada manajemen inventaris.

TAPI. Anda mungkin ingin menampilkan tingkat persediaan pada halaman web, atau Anda mungkin ingin menampilkan nomor edisi persediaan dalam stok (bayangkan inventaris Anda adalah buku, majalah, dll). Informasi ini berasal dari domain Inventaris.

Jadi, bagaimana Anda menangani ini? Maukah kamu

a) Memuat domain Produk dan agregat domain Inventaris? b) Apakah Anda memiliki beberapa properti pada entitas domain Produk Anda untuk nomor dalam stok, dan edisi dalam stok, dan kemudian menggunakan Acara Domain untuk memperbarui ini ketika entitas Inventaris diperbarui?

Satu pertanyaan terakhir. Saya tahu kita harus melupakan / mengabaikan kegigihan domain dan hanya memikirkan domain tersebut. Tapi hanya untuk memikirkan ini, dalam contoh di atas kita akan berakhir dengan berpotensi 2 tabel DB untuk katalog produk dan inventaris produk. Sekarang, apakah kita menggunakan pengidentifikasi yang sama karena ini adalah produk yang sama. Atau, dapatkah kita menggunakan 1 tabel dan 1 baris tabel untuk data dan hanya memetakan data yang relevan ke properti agregat?

PendorPaul
sumber

Jawaban:

8

Anda mungkin ingin menampilkan tingkat persediaan pada halaman web, atau Anda mungkin ingin menampilkan nomor edisi persediaan dalam stok (bayangkan inventaris Anda adalah buku, majalah, dll). Informasi ini berasal dari domain Inventaris.

Hal utama yang perlu diperhatikan pada saat ini adalah bahwa Anda berbicara tentang tampilan, yang mengatakan bahwa menggunakan data basi dapat diterima.

Karena itu, Anda tidak perlu berinteraksi dengan agregat (yang bertanggung jawab untuk mencegah perubahan dari pelanggaran invarian bisnis), tetapi dengan representasi salinan terbaru dari status agregat.

Jadi apa yang biasanya saya harapkan adalah menjalankan kueri terhadap Katalog Produk, dan satu lagi menjalankan terhadap Inventaris, dan sesuatu untuk menyusun keduanya menjadi DTO yang Anda butuhkan untuk mendukung tampilan.

Muat domain Produk dan agregat domain Inventaris?

Jadi itu dekat . Kami tidak perlu memuat agregat, karena kami tidak akan mengubah apa pun. Tetapi kita membutuhkan negara mereka; jadi kita bisa memuatnya. Yang mengatakan, saya biasanya berharap dua domain akan berjalan dalam proses yang berbeda. Karena itu, kami akan memanggil keduanya, bukan memuat keduanya.

Apakah Anda memegang beberapa properti pada entitas domain Produk Anda untuk nomor dalam stok, dan edisi dalam stok, dan kemudian menggunakan Acara Domain untuk memperbarui ini ketika entitas Inventaris diperbarui?

"Jangan menyeberangi sungai. Itu akan buruk."

Menggunakan peristiwa untuk mengoordinasikan informasi di seluruh konteks domain: ide bagus . Mendorong konsep yang termasuk dalam satu domain ke domain lain: kebalikan dari ide bagus, kecuali lebih dari itu.

Anda ingin menjaga domain tetap bersih. The aplikasi yang berinteraksi dengan domain, itu tidak begitu penting. Jadi misalnya, masuk akal untuk aplikasi Inventaris untuk memanggil layanan di aplikasi produk untuk menanyakan beberapa konsep spesifik produk untuk ditambahkan ke tampilan. Atau sebaliknya.

Saya tidak tahu alasan mengapa satu aplikasi perlu dibatasi untuk satu domain. Selama ada satu sumber kebenaran, Anda dapat mendistribusikan transaksi sesuka Anda.

Tapi hanya untuk memikirkan ini, dalam contoh di atas kita akan berakhir dengan berpotensi 2 tabel DB untuk katalog produk dan inventaris produk. Sekarang, apakah kita menggunakan pengidentifikasi yang sama karena ini adalah produk yang sama.

Itu akan menjadi cara yang mudah. Dalam istilah yang lebih besar, Anda menggunakan pengidentifikasi yang sama karena entitas dunia nyata adalah sama; dua konteks terikat yang berbeda memodelkan entitas itu secara berbeda, tetapi model itu bukanlah entitas dunia nyata.

Ketika itu tidak berhasil, maka Anda akan memerlukan beberapa permintaan untuk menjembatani kesenjangan. Saya pikir variasi paling umum dari ini adalah bahwa entitas yang lebih baru mempertahankan id dari entitas yang lebih tua. Anda akan melihat ini dalam satu BC juga: pelamar, ketika disetujui, menjadi klien. Ini adalah agregat yang berbeda (keadaan yang terkait dengan klien tunduk pada invarian yang berbeda dari pelamar); jadi jika lapisan kegigihan Anda menggunakan aliran acara, aliran untuk agregat baru akan membutuhkan pengidentifikasi yang berbeda. Jadi akan ada sedikit negara di suatu tempat yang mengatakan "pelamar ini menjadi klien ini".

Atau, dapatkah kita menggunakan 1 tabel dan 1 baris tabel untuk data dan hanya memetakan data yang relevan ke properti agregat?

YIKES! Tidak, jangan lakukan itu. Anda menambahkan pertentangan transaksi tanpa alasan bisnis untuk melakukannya.

VoiceOfUnreason
sumber
Saya telah mencentang ini sebagai jawabannya, kredit juga untuk @guillaume di bawah ini yang juga menunjukkan bahwa membaca data untuk ditampilkan dalam tampilan tidak memerlukan memuat agregat. Terima kasih atas jawaban terperinci yang panjang. Berasal dari pendekatan model data "tradisional" pertama saya merasa sulit memaksa diri saya untuk melupakan lapisan kegigihan dan fokus pada bahasa domain. Tepat ketika saya pikir saya sudah mendapatkannya, saya membaca artikel lain yang menghancurkan pemahaman saya.
PendorPaul
Saya baru saja membaca artikel ini msdn.microsoft.com/en-us/magazine/dn802601.aspx yang merinci menggunakan Peristiwa Domain untuk menduplikasi beberapa data antara konteks. Contohnya berbagi daftar pelanggan antara layanan pelanggan dan sistem pemrosesan pesanan. Ini menggandakan data pelanggan dalam sistem pemesanan, dan menggunakan Acara untuk menyinkronkan data. Ini terbang di hadapan apa yang kita jawab di sini. Tentunya dalam sampel yang ditautkan konteks pesanan hanya membutuhkan customerID, dan yang dapat diisi dari aplikasi yang memiliki akses ke konteks layanan pelanggan.
PendorPaul
Anda akan ingin menjadi sangat tepat dalam pemikiran Anda, di sini. Menyalin data antar sistem BUKAN sama dengan menyalin data antar model domain. Setiap kali Anda melihat "read only [bergumam]", itu adalah petunjuk besar bahwa data tidak termasuk dalam domain itu (bahkan jika aplikasi mungkin masih peduli tentang itu).
VoiceOfUnreason
Ya, itulah yang saya pikirkan juga. Pergeseran proses berpikir cukup sulit tanpa "ahli" menerbitkan artikel yang mengeruhkan air. Saya telah menghabiskan hari ini benar-benar menganalisis domain saya, untuk mencoba dan benar-benar memahami di mana BC dan Agregat Root saya berada. Saya cukup banyak di sana, tetapi juga saya tahu saya dapat memperbaiki dan memperbaiki model saya saat saya pergi. Saya telah terjebak di neraka analisis selama berhari-hari sekarang, khawatir untuk mulai menulis kode takut bahwa saya tidak memiliki DDD langsung di kepala saya. Saya pikir lebih baik untuk melanjutkan, dan terus mempertanyakan kode saya, dan apakah modelnya benar. Saya akan ke sana. Terima kasih
PendorPaul
Mungkin saya salah membaca, tetapi praktik yang saya percaya Anda ajak bicara disebut Transfer Keadaan Acara-Carried (Transfer Keadaan Acara) dan itu bisa menjadi model yang sangat kuat terutama untuk tampilan dasbor / tabel di mana Anda perlu memfilter dan data halaman lintas layanan. Anda dapat membuat "proyeksi" (pada dasarnya tampilan) dari peristiwa domain untuk mendorong dasbor ini. Saya telah menggunakannya sebelumnya dengan cukup sukses. Ini bisa menjadi alat yang sangat kuat dalam skenario yang tepat. IMHO, yang lebih penting di sini adalah Anda menyadari bahwa proyeksi ini tidak mewakili model domain dan tidak boleh mengandung logika bisnis.
Jordan
3

Saya pikir pertanyaan Anda benar-benar membutuhkan 2 set pilihan orthogonal -

  • Apakah Anda memuat dua objek dan menyajikan datanya bersama-sama atau Anda memuat 1 objek yang berisi semua yang Anda inginkan?

  • Apakah Anda menggunakan agregat untuk menampilkan barang, atau yang lainnya?

Jika Anda percaya pada pendekatan CQRS, ternyata agregat mungkin bukan taruhan terbaik untuk dibaca. Setiap kali Anda memuat agregat, apakah akan menampilkan data atau memodifikasinya, Anda menambahkan konkurensi dan pertikaian ke sistem Anda. Juga, agregat berpotensi lebih besar dan lebih lambat untuk dimuat daripada jika Anda menggunakan model baca ad-hoc yang dirancang khusus untuk tampilan.

Solusi a) dari Q Anda tampaknya mengalami banyak jebakan ini. Opsi b) dapat valid, tetapi saya akan menggunakannya hanya jika data dari InventoryManagementBC diperlukan untuk menegakkan invarian ketika memutasikan Productagregat. Lebih baik jika agregat berisi semua data yang diperlukan untuk memeriksa aturan bisnisnya setelah modifikasi, tetapi di sisi baca mereka dapat duduk di mana saja.

Mengenai data, rekomendasi umum adalah memberikan Bounded Contexts database mereka sendiri (untuk alasan penerapan dan alasan SoC). Anda mungkin harus menggunakan pengidentifikasi yang sama jika Anda ingin mencocokkan produk di antara kedua BC.

Tentang interaksi lintas-BC, Anda mungkin juga ingin melihat /programming/16713041/communicating-between-two-bounded-contexts-in-ddd

guillaume31
sumber
1
Oke, itu membantu. Pada dasarnya kami menggunakan Aggregate Roots dan BC untuk memastikan invarian kami konsisten, dan data kami valid, dan operasi yang ingin kami lakukan terbungkus dalam agregat atau BC kami. Ketika datang untuk membaca dan menampilkan data itu, kita bisa mengatasinya secara terpisah dan ringan tanpa semua agregat / BC terhidrasi. Lagi pula, mengapa kita perlu memuat Agregat ketika semua yang kita lakukan adalah menampilkan data baik dalam laporan atau di layar. Ini masuk akal. Terima kasih.
PendorPaul
Di sinilah CQRS benar-benar bersinar. Anda bisa melakukan kueri SQL, bergabung dengan tabel, dan mengembalikan kueri yang disesuaikan untuk tampilan tertentu. Ini juga menghapus repo Anda dari kekacauan metode kueri. Juga, Anda bahkan dapat mereplikasi data pada layanan seperti ElasticSearch dan menanyakannya.
notnotmatter
1

DDD dimaksudkan untuk aplikasi yang logika bisnisnya kompleks. "cetak sesuatu" bukanlah logika bisnis yang kompleks. Ini sebenarnya bukan logika bisnis sama sekali.

Jika, logika bisnis dalam satu konteks memerlukan beberapa informasi untuk menangani beberapa kasus penggunaan, maka informasi tersebut merupakan bagian dari konteks itu. Jadi ide bahwa konteks terbatas mungkin memerlukan informasi yang tersedia dalam konteks terbatas berbeda tidak masuk akal, karena konteks terbatas memiliki semua informasi yang dibutuhkan.

Euforia
sumber
OK, jadi ambillah sesuatu seperti Amazon, itu sistem yang kompleks dengan logika bisnis yang rumit. Mereka memiliki manajemen katalog dan manajemen inventaris. Mereka tidak memerlukan total inventaris untuk mengelola katalog, maksud saya nama produk, deskripsi, jenis, kondisi, dll. Namun, mereka menunjukkan jumlah item dalam stok di halaman depan toko mereka. Dalam skenario itu, di mana Anda ingin memisahkan Manajemen Katalog Produk dan domain Inventaris Produk Anda, tetapi Anda perlu menampilkan beberapa informasi tentang inventaris pada halaman produk Anda, bagaimana Anda melakukannya?
PendorPaul
Saya kira yang saya katakan adalah domain Katalog Produk memiliki semua informasi yang diperlukan untuk mengelola katalog produk. Domain Inventaris memiliki semua informasi yang diperlukan untuk mengelola inventaris. Namun, ketika saya ingin menampilkan beberapa informasi kepada pengguna, dan data itu berasal dari 2 domain, di mana saya melakukannya. Apakah saya hanya memuat kedua domain di UI saya dan mengikat properti yang ingin saya tampilkan? Atau apakah saya memiliki mekanisme pelaporan / pembacaan di mana saya mengembalikan tipe anonim atau DTO yang berisi data yang saya butuhkan untuk UI saya?
PendorPaul
Sangat lucu melihat kembali komentar lama saya 11 bulan yang lalu, tapi sepertinya seumur hidup. Anda benar-benar benar Euforia tentang aspek baca dan tulis. Aplikasi yang saya kerjakan telah berkembang sedikit seiring dengan pemahaman saya yang telah berkembang. Saya sekarang menggunakan metode CQRS, melalui Jimmy Bogards Mediatr. Fleksibilitas semata-mata memiliki perintah yang berinteraksi dengan Agregat, tetapi kemudian menggunakan kueri dan penangan permintaan untuk mengembalikan apa pun yang saya butuhkan untuk tampilan luar biasa. Bungkus itu ke dalam Views yang memanggil QueryHandlers tersebut, dan decouplingnya bagus untuk yang satu ini. Terima kasih
PendorPaul
@PendorPaul, saya pikir saya di mana Anda berada 11 (sekarang 13) bulan lalu. Apa yang membuat Anda sampai di tempat Anda sekarang?
Greg Bell
1
@GregBell Anda harus memaksakan perubahan pola pikir. Saya terjebak dalam pendekatan "desain database, membangun tingkat data, membangun beberapa logika bisnis ... dll". Dan saya fokus pada menciptakan semua entitas yang mencakup. yaitu "Produk" di situs eCommerce, yang menangani semuanya mulai dari harga, deskripsi, inventaris, lokasi stok .... tetapi itu menjadi sangat kompleks. Pendekatan konteks terbatas berarti dalam konteks Persediaan, "Produk" hanya berisi info dan perilaku untuk manajemen inventaris. Deskripsi dan gambar dikelola dalam konteks konten, penetapan harga dalam konteks penetapan harga.
PendorPaul
1

Dari sudut pandang saya ada definisi yang berbeda dari "Produk" - setiap konteks-batas memiliki definisi sendiri tentang "produk" -domain:

  • Dalam Context-Management-Bounding-Context suatu produk memiliki gambar dan teks deskripsi.
  • Dalam konteks inventaris-terikat-produk memiliki jumlah stok, penjual produk, meramalkan kapan produk akan tersedia
  • Dalam Konteks Harga-Caculation-Bounding-ada aturan berapa biaya produk per kuantitas.

Selain itu, saya akan menambahkan konteks Shop-Bounding-Context tambahan dengan definisi produknya sendiri (kombinasi yang relevan dari domain produk dari konteks Bounding-Contexts lainnya).

Produk Toko akan memiliki "gambar dan teks deskripsi" dari konten dan ketersediaan dari "Inventaris" tetapi bukan "penjual produk" dari inventaris.

Konteks Shop-Bounding-tambahan ini tergantung pada Konten, Inventarisasi, Harga Bounding-Context

k3b
sumber
Jadi, bagaimana Anda membuat Shop-Product BC itu? Dalam konteks itu apakah Anda memiliki referensi ke Produk dan Inventaris BC, dan apakah Anda menghidrasi mereka dari toko kegigihan Anda ketika Anda memuat BC Produk Toko, dan kemudian menawarkan properti yang Anda inginkan dari BC tersebut melalui properti StoreProduct Anda? Saya menemukan artikel ini sebenarnya yang sejalan dengan apa yang saya pikirkan, lintas acara BC tetapi @ guillaume13 di atas telah menunjukkan bahwa untuk tujuan tampilan saya dapat menghindari BC dan hanya menarik kembali data yang saya butuhkan untuk pandangan saya. msdn.microsoft.com/en-us/magazine/dn802601.aspx
PendorPaul