Bagaimana cara merancang batas agregat?

10

Saya ingin menulis aplikasi seperti e-commerce.

Dan Anda tahu bahwa dalam aplikasi yang serupa produk bisa memiliki sifat dan fitur yang berbeda. Untuk mensimulasikan kesempatan seperti itu, saya telah membuat entitas model domain berikut:

Kategori - ini adalah sesuatu seperti "elektronik> komputer" yaitu jenis produk. Сategori berisi daftar properti (Daftar <Properti>).

Properti - entitas independen yang berisi nama, satuan ukuran, tipe data. Misalnya "nama", "berat", "ukuran layar". Properti yang sama dapat memiliki produk yang berbeda.

Produk - hanya berisi nama dan daftar nilai yang berkaitan dengan properti. Nilai adalah objek yang hanya berisi bidang nilai dan id bidang properti.

Saya awalnya memutuskan untuk membuat Kategori seperti agregat tunggal dalam skema ini karena misalnya ketika saya menambahkan produk baru, saya perlu mengetahui semua data yang terkait dengan kategori saat ini termasuk properti yang terkait dengan kategori saat ini ( kategori. Tambahkan Produk Baru (produk) ). Tapi apa yang harus saya lakukan ketika saya hanya perlu menambahkan properti baru yang bukan milik kategori apa pun. Sebagai contoh, saya tidak dapat melakukan kategori ini. Tambahkan Properti (properti) karena ia dengan jelas mengatakan bahwa kami menambahkan properti ke kategori tertentu.

Oke langkah selanjutnya saya memutuskan Properti terpisah menjadi agregat terpisah tetapi kemudian akan menjadi daftar dengan entitas sederhana.

Tentu saja saya dapat membuat sesuatu seperti PropertyAggregate agar tetap di dalam daftar properti dan aturan bisnis tetapi ketika saya menambahkan produk, saya harus memiliki di dalam kategori seluruh daftar properti yang termasuk dalam kategori ini untuk memeriksa invarian. Tetapi saya juga sadar bahwa menjaga tautan di dalam agregat pada agregat lain adalah praktik yang buruk.

Apa saja pilihan untuk mendesain kasing bisnis ini?

cephei
sumber
Bisakah Anda memberikan contoh kategori, properti, dan produk yang lebih lengkap? Elektronik atau komputer akan menjadi kategori, iPhone X akan menjadi contoh produk, dan properti akan menjadi apa sebenarnya? Layar 11 "inci?
Neil
kamu hampir benar. Saya menambahkan beberapa klarifikasi
cephei
Tampaknya Anda melihat desain agregat secara eksklusif dari perspektif "wadah data". Anda mungkin juga ingin memikirkan tentang kasus penggunaan aplikasi Anda, dengan mempertimbangkan aspek transaksional, kolaborasi / akses bersamaan, peristiwa yang terjadi, transisi negara, dll.
guillaume31

Jawaban:

7

Dalam perspektif DDD Category,, Productdan Propertyadalah entitas: mereka semua sesuai dengan objek yang memiliki identitas mereka sendiri.

Opsi 1: desain asli Anda

Anda membuat Categoryroot dari agregat tunggal. Di satu sisi, ini masuk akal, karena agregat harus memastikan konsistensi ketika objek yang dimodifikasi, dan Productharus memiliki Propertiesnya Category:

masukkan deskripsi gambar di sini

Tetapi di sisi lain, agregat tunggal berarti bahwa semua objeknya terkait dengan root yang memilikinya, dan semua referensi eksternal harus dibuat melalui root agregat ini. Ini menyiratkan bahwa:

  • satu spesifik Productmilik satu dan hanya satu Category. Jika Categorydihapus, itu juga miliknya Products.
  • spesifik Propertymilik satu dan hanya satu Category. Jika tidak dikatakan, jika "layar TV" dan "Monitor komputer" akan menjadi dua kategori, "Layar TV: ukuran" dan "Monitor komputer: ukuran" akan menjadi dua properti yang berbeda.

Poin kedua tidak sesuai dengan narasi Anda: " Tapi apa yang harus saya lakukan ketika saya hanya perlu menambahkan yang baru Propertyyang tidak termasuk dalam kategori apa pun ". Dan tidak jelas apakah hal yang sama Propertiesdapat digunakan secara berbeda Categories.

Opsi 2: Properti di luar agregat

Jika Propertyada secara independen dari Categories, itu harus di luar agregat. Dan sama jika Anda ingin berbagi di Propertiesantara Categories(yang masuk akal untuk tinggi, lebar, ukuran, dll ...). Tampaknya ini benar-benar kasusnya.

Konsekuensinya adalah pada tautan antara Propertydan hal-hal yang termasuk dalam agregat: sementara Anda dapat menavigasi dari bagian dalam agregat ke Property, Anda tidak lagi diizinkan untuk langsung dari dari Propertyke nilai yang sesuai. Pembatasan kemampuan navigasi ini dapat ditampilkan dalam diagram UML:

masukkan deskripsi gambar di sini

Perhatikan bahwa desain ini tidak mencegah Anda untuk List<Property>masuk Category, dengan semantik referensi (misalnya java): setiap referensi dalam daftar merujuk ke Propertyobjek yang dapat dibagi dalam repositori.

Satu-satunya masalah dengan desain ini adalah Anda dapat mengubah Propertyatau menghapusnya: karena di luar agregat, agregat tidak dapat menjaga konsistensi invariannya. Tapi ini bukan masalah. Ini adalah konsekuensi dari prinsip-prinsip DDD dan kompleksitas dunia nyata. Berikut kutipan dari Eric Evans dalam bukunya yang seminal " Desain Berbasis Domain: Mengatasi Kompleksitas di Jantung Perangkat Lunak ":

Aturan apa pun yang mencakup AGREGAT tidak akan diharapkan selalu terbaru setiap saat. Melalui pemrosesan peristiwa, pemrosesan batch, atau mekanisme pembaruan lainnya, dependensi lain dapat diselesaikan dalam waktu tertentu. Tetapi invarian yang diterapkan dalam AGREGAT akan diberlakukan dengan selesainya setiap transaksi.

Jadi ya, jika Anda mengubah a Property, Anda harus memastikan bahwa layanan memeriksa Kategori yang merujuknya diperbarui sesuai kebutuhan.

Opsi 3: Kategori, Properti, dan Produk dalam agregat berbeda

Saya hanya ingin tahu apakah asumsi bahwa Productmilik seseorang Categorydidasarkan:

  • Saya sering melihat toko online mengusulkan satu di Productbawah beberapa Categories. Misalnya, Anda akan menemukan "Laptop Merek X Model Y" di bawah kategori "Laptop" dan kategori "Komputer", dan "printer multifungsi Z" di bawah kategori "printer", "pemindai" dan "faks".
  • Mungkinkah seseorang membuat yang Productpertama, dan baru kemudian menugaskannya ke Kategori dan mengisi nilainya?
  • Jika Anda ingin membagi kategori, apakah Anda benar-benar akan menghapus Produknya dan kemudian membuatnya kembali di bawah kategori baru?

Itu tidak akan menyederhanakan agregat, dan Anda akan memiliki lebih banyak aturan yang menjangkau agregat. Tetapi sistem Anda akan menjadi lebih banyak bukti di masa depan.

Christophe
sumber
Terima kasih banyak, ini adalah penjelasan yang sangat berguna. Tetapi saya ingin mengklarifikasi beberapa poin. Saya ingin memulai dengan opsi kedua dan siapa tahu, mungkin saya akan sampai pada yang ketiga. Jika saya mengambil Propertymelampaui batas Categoryagregat, apakah ini berarti Propertyagregat itu sendiri dan memerlukan repositori? Jika itu benar maka bagaimana cara lulus diperlukan List<Property>menjadi Categorycontoh? Melalui konstruktor? Itu akan benar? Dan bagaimana cara mengetahui daftar PropertyID Categoryyang belum dibuat?
cephei
@zetetic singkatnya: ya, Anda akan memerlukan repositori properti independen. Entah Anda meneruskan daftar Properti yang ada ke pabrik Kategori, atau Anda membuat Kategori kosong dan mengisi daftar dengan metode addProperty. Sebagai imbalannya: bayangkan Anda ingin memiliki Properti "wajib" dan "opsional", dan karakteristik wajib tergantung pada kategorinya. Bagaimana kamu akan mengatasi ini ?
Christophe
menjawab pertanyaan Anda hal pertama yang terlintas dalam pikiran adalah bahwa saya dapat membuat entitas khusus Featuredan hanya akan menjadi milik Product. dan entitas ini tidak akan berpartisipasi dalam pencarian. apa yang kamu katakan ?
cephei
@etiketapi kenapa tidak! Saya telah meninggalkan Nilai karena mereka saat ini dalam produk, dan akan ave menghubungkan fitur ke kategori. Kategori memiliki n fitur (bagian dari agregatnya), Properti mendefinisikan m Fitur (tetapi tautan masuk melalui fitur Category->). Anda kemudian telah menguraikan hubungan banyak ke banyak menjadi elemen yang lebih mudah dikelola, memperjelas batas agregat. Akhirnya tentang injeksi repositori: ini tidak diperlukan jika Anda mereferensikan agregat lain berdasarkan identitas (baca artikel ini informit.com/articles/article.aspx?p=2020371&seqNum=4 )
Christophe
5

Seperti yang saya lihat, Anda dapat menyelesaikan ini dalam salah satu dari dua cara:

Kategori adalah jenis produk khusus

Ini berarti untuk setiap produk yang diberikan dalam database Anda, itu berisi kunci asing yang menunjuk ke produk tabel yang sama. Suatu produk adalah produk hanya jika tidak ada produk yang kunci asingnya sama dengan id produk tersebut. Dengan kata lain, jika tidak ada produk di bawahnya, itu adalah produk.

Ini akan menyederhanakan banyak hal. Produk ke properti akan memiliki hubungan satu-ke-banyak dan karena itu juga kategori Anda memiliki hubungan satu-ke-banyak karena mereka juga produk. Menambahkan properti ke kategori akan semudah menambahkan properti ke produk di program Anda. Memuat semua properti berarti menggabungkan sifat-sifat produk dengan sifat-sifat produk kategori terkait dan seterusnya hingga Anda mencapai produk kategori tanpa induk.

Aplikasi e-niaga Anda perlu membuat perbedaan ini, tetapi jika Anda cenderung memuat produk dari suatu kategori, itu bukan kerugian kinerja untuk mengetahui jika Anda berurusan dengan suatu kategori atau suatu produk. Ini juga cocok untuk pencarian dengan cara pohon ke tingkat produk karena setiap produk (kategori) akan membuka daftar sub-produk tanpa banyak pekerjaan tambahan.

Kelemahan dari hal ini tentu saja info tambahan hadir dalam produk yang tidak masuk akal untuk suatu kategori akan membuat bidang yang tidak digunakan canggung dalam produk. Meskipun solusi ini akan lebih fleksibel dalam aplikasi Anda, itu juga agak kurang intuitif.

Hubungan many-to-many

Produk tidak lagi dalam hubungan komposit dengan properti. Anda membuat tabel ProductProperty dengan kunci asing dari tabel produk dan tabel properti yang menghubungkan keduanya. Demikian juga, Anda memiliki tabel kategori dengan hubungan banyak-ke-banyak dengan tabel properti dan tabel CategoryProperty dengan kunci asing dari tabel kategori dan tabel properti.

Produk itu sendiri akan memiliki hubungan banyak-ke-satu dengan kategori, memungkinkan Anda untuk secara esensial membuat daftar properti unik yang berkaitan dengan produk dan kategori melalui pernyataan pilih yang diformalkan dengan baik.

Dari sudut pandang basis data, ini jelas lebih bersih dan lebih fleksibel. Aplikasi Anda mungkin bisa dilakukan sebagian besar tanpa berurusan langsung dengan CategoryProperty atau ProductProperty jika kueri dilakukan dengan benar. Namun Anda juga tidak boleh memperlakukan kategori atau produk sebagai pemilik properti. Itu harus menjadi entitas sendiri dalam program Anda. Ini juga berarti pengelolaan properti tersebut akan menjadi masalah menciptakan properti itu sendiri, kemudian mengaitkannya dengan kategori atau produk dalam dua langkah terpisah. Tentu saja lebih banyak pekerjaan daripada solusi pertama, tetapi tidak berarti lebih sulit.

Selain itu, Anda juga harus melakukan pemeriksaan tambahan pada penghapusan kategori atau produk jika salah satu propertinya digunakan oleh orang lain (tidak seperti solusi pertama di mana Anda dapat dengan aman menghilangkan semua properti terkait dari suatu produk / kategori tertentu) .

Kesimpulan

Dalam konteks profesional, saya akan berusaha lebih keras dan kategori jarak dari produk dan produk dari properti menggunakan pendekatan banyak ke banyak. Tidak akan ada kemungkinan tumpang tindih data, dan dalam arti, lebih mudah untuk menganggap masing-masing ketiganya sebagai entitasnya sendiri. Namun, tidak berarti solusi pertama yang buruk karena juga memungkinkan Anda menulis aplikasi yang lebih sederhana. Ketahuilah bahwa jika Anda berpikir bahwa pada akhirnya Anda mungkin perlu beralih dari satu solusi ke solusi yang lain, mungkin akan menjadi kepentingan Anda untuk memilih yang kedua.

Semoga berhasil!

Neil
sumber
Terima kasih atas jawaban terperinci dan menarik! pada tingkat basis data saya telah memodelkan seperti yang Anda jelaskan dalam kasus kedua, pola ini disebut entitas-atribut-nilai tetapi saya terjebak pada level kode yaitu definisi agregat. Dalam kebanyakan kasus, semua entitas ini digunakan bersama. dimungkinkan untuk menggabungkan menjadi satu agregat tetapi ada kasus-kasus yang seperti mengisi direktori yang pada dasarnya dikalahkan dari agregat.
cephei