Evans memperkenalkan dalam bukunya "Domain Driven Design" di Bab 6 "Agregat" konsep Agregat. Dia lebih jauh mendefinisikan aturan untuk menerjemahkan konsep itu ke dalam implementasi (Evans 2009, hlm. 128-129):
Root ENTITY dapat menyerahkan referensi ke ENTITAS internal ke objek lain, tetapi objek tersebut dapat menggunakannya hanya sementara, dan mereka mungkin tidak berpegang pada referensi.
Setelah menguraikan aturan lain, ia merangkumnya ke dalam paragraf ini:
Cluster Entitas dan Nilai Objek menjadi Agregat dan menentukan batas-batas di sekitar masing-masing. Pilih satu Entitas untuk menjadi root dari setiap Agregat, dan kontrol semua akses ke objek di dalam batas melalui root. Izinkan objek eksternal untuk menyimpan referensi ke root saja. Referensi sementara untuk anggota internal dapat dikeluarkan untuk digunakan dalam satu operasi saja. Karena root mengontrol akses, ia tidak bisa dibohongi oleh perubahan pada internal. Pengaturan ini membuatnya praktis untuk menegakkan semua invarian untuk objek dalam Agregat dan untuk Agregat secara keseluruhan dalam setiap perubahan negara.
Jadi apa sebenarnya arti dari penggunaan sementara?
Kolega saya mengerti bahwa hanya root agregat yang memperlihatkan antarmuka publik untuk klien. Klien tidak akan memiliki kesempatan untuk memanggil operasi apa pun pada entitas selain dari akar agregat.
Pemahaman saya tentang kalimat yang dikutip berbeda. Saya mengerti bahwa itu memang secara eksplisit memungkinkan klien memanggil operasi pada entitas internal. Namun hanya setelah mendapatkannya dari root.
Jadi, mari kita ambil contoh konkret:
Misalkan a Cart
terdiri dari banyak Items
. Masing-masing Item
memiliki a Quantity
. Model harus mendukung use case "Tingkatkan jumlah satu Item tertentu". Tidak ada invarian yang bisa dilanggar yang memengaruhi apa pun di luar Item.
Apakah model melanggar aturan yang dikutip di atas, ketika klien dapat melakukan ini dengan menelepon cart.item(itemId).increaseQuantity()
atau haruskah klien hanya diizinkan untuk memanggil cart.increaseItemQuantity(itemId)
? Apa manfaat yang terakhir?
sumber
cart.increaseItemQuantity(itemId)
, jika tidak ada alasan lain selain kurang dari pelanggaran Hukum Demeter. Meneleponcart.increaseItemQuantity(itemId)
memungkinkan Anda melakukan hal-hal seperti memperbarui jumlah total keranjang.Jawaban:
Selama
Item
tidak bisa eksis tanpaCart
juga hadir, maka tidak ada perbedaan antara kedua opsi tersebut. Dimungkinkan untuk menyimpan invarian dalam kedua kasus.Dalam kasus metode sedang
Item
,Item
dapat "memberitahukan" itu keranjang induk untuk memeriksa invarian ketika perlu mengubah keadaan itu sendiri. Hal ini membuat hal-hal sedikit lebih rumit, karena ada ketergantungan siklus antaraItem
danCart
(yang saya anggap tidak masalah berkat asumsi dalam kalimat pertama dan sesuatu yang perlu ada IMO baik cara).Dalam hal metode aktif
Cart
, itu membuatnya lebih sederhana, karena tidak perlu untukItem
referensiCart
. Tetapi itu membuatnya rumit karena sekarang metode tidak hanya memeriksa invarian dan apakah negara berubah. Tapi itu juga perlu memastikan item (atau ID) itu valid untuk iniCart
. Dalam kasus lain, ini sudah ditangani dengan metode yang menanyakan item yang diberikan dari troli.tl; dr; Kedua opsi memiliki kelebihan dan kekurangan yang jelas dan tidak ada yang tampaknya lebih baik atau lebih buruk daripada yang lain.
sumber