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?
Jawaban:
Dalam perspektif DDD
Category
,,Product
danProperty
adalah entitas: mereka semua sesuai dengan objek yang memiliki identitas mereka sendiri.Opsi 1: desain asli Anda
Anda membuat
Category
root dari agregat tunggal. Di satu sisi, ini masuk akal, karena agregat harus memastikan konsistensi ketika objek yang dimodifikasi, danProduct
harus memilikiProperties
nyaCategory
: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:
Product
milik satu dan hanya satuCategory
. JikaCategory
dihapus, itu juga miliknyaProducts
.Property
milik satu dan hanya satuCategory
. 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
Property
yang tidak termasuk dalam kategori apa pun ". Dan tidak jelas apakah hal yang samaProperties
dapat digunakan secara berbedaCategories
.Opsi 2: Properti di luar agregat
Jika
Property
ada secara independen dariCategories
, itu harus di luar agregat. Dan sama jika Anda ingin berbagi diProperties
antaraCategories
(yang masuk akal untuk tinggi, lebar, ukuran, dll ...). Tampaknya ini benar-benar kasusnya.Konsekuensinya adalah pada tautan antara
Property
dan hal-hal yang termasuk dalam agregat: sementara Anda dapat menavigasi dari bagian dalam agregat keProperty
, Anda tidak lagi diizinkan untuk langsung dari dariProperty
ke nilai yang sesuai. Pembatasan kemampuan navigasi ini dapat ditampilkan dalam diagram UML:Perhatikan bahwa desain ini tidak mencegah Anda untuk
List<Property>
masukCategory
, dengan semantik referensi (misalnya java): setiap referensi dalam daftar merujuk keProperty
objek yang dapat dibagi dalam repositori.Satu-satunya masalah dengan desain ini adalah Anda dapat mengubah
Property
atau 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 ":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
Product
milik seseorangCategory
didasarkan:Product
bawah beberapaCategories
. 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".Product
pertama, dan baru kemudian menugaskannya ke Kategori dan mengisi nilainya?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.
sumber
Property
melampaui batasCategory
agregat, apakah ini berartiProperty
agregat itu sendiri dan memerlukan repositori? Jika itu benar maka bagaimana cara lulus diperlukanList<Property>
menjadiCategory
contoh? Melalui konstruktor? Itu akan benar? Dan bagaimana cara mengetahui daftarProperty
IDCategory
yang belum dibuat?Feature
dan hanya akan menjadi milikProduct
. dan entitas ini tidak akan berpartisipasi dalam pencarian. apa yang kamu katakan ?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!
sumber