Bisakah klien memanggil metode pada entitas selain dari agregat root?

10

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 Cartterdiri dari banyak Items. Masing-masing Itemmemiliki 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?

Markus Malkusch
sumber
Mana yang lebih masuk akal dari perspektif bisnis?
Robert Harvey
Itu contoh buatan. Pertanyaan saya adalah tentang penafsiran dua paragraf yang dikutip dari buku Evans. Tetapi para ahli domain buatan akan berbicara tentang "meningkatkan jumlah item keranjang". Jadi gerobak, barang dan kuantitas adalah bagian dari UL.
Markus Malkusch
1
Teladan Anda tidak lebih tiruan dari fatwa Evans. Mungkin bermanfaat untuk menunjukkan bahwa DDD sebenarnya bukan teknik pemrograman, meskipun ada banyak orang yang mencoba menggunakannya dengan cara itu.
Robert Harvey
Bisakah Anda membagikan sedikit lebih banyak teks dari buku, sehingga kutipan tanpa tubuh Anda memiliki lebih banyak konteks?
Robert Harvey
2
Ya terima kasih. Apa yang dikatakan Evans adalah bahwa Anda harus membiarkan Root Agregat untuk mengontrol keadaan internalnya sendiri (praktik yang baik untuk kelas mana pun, sebenarnya). Oleh karena itu mungkin lebih masuk akal untuk membiarkan kereta untuk mengontrol peningkatan kuantitas dengan cart.increaseItemQuantity(itemId), jika tidak ada alasan lain selain kurang dari pelanggaran Hukum Demeter. Menelepon cart.increaseItemQuantity(itemId)memungkinkan Anda melakukan hal-hal seperti memperbarui jumlah total keranjang.
Robert Harvey

Jawaban:

2

Selama Itemtidak bisa eksis tanpa Cartjuga hadir, maka tidak ada perbedaan antara kedua opsi tersebut. Dimungkinkan untuk menyimpan invarian dalam kedua kasus.

Dalam kasus metode sedang Item, Itemdapat "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 antara Itemdan Cart(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 untuk Itemreferensi Cart. 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 ini Cart. 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.

Euforia
sumber