Saya memulai dengan DDD dan memahami bahwa akar agregat digunakan untuk memastikan konsistensi transnasional. Kita tidak boleh memodifikasi beberapa agregat dalam satu layanan aplikasi.
Namun saya ingin tahu bagaimana menghadapi situasi berikut.
Saya memiliki akar agregat yang disebut Produk.
Ada juga root agregat yang disebut Group.
Keduanya memiliki ID, dan dapat diedit secara mandiri.
Banyak Produk dapat mengarah ke Grup yang sama.
Saya memiliki layanan aplikasi yang dapat mengubah grup produk:
ProductService.ChangeProductGroup(string productId, string groupId)
- Grup cek ada
- Dapatkan produk dari repositori
- Atur grupnya
- Tulis produk kembali ke repositori
Saya juga memiliki layanan aplikasi tempat grup dapat dihapus:
GroupService.DeleteGroup(string groupId)
1. Dapatkan produk dari repositori yang groupIdnya disetel ke groupId yang disediakan, pastikan penghitungannya 0 atau batal 2. Hapus grup dari repositori grup 3. Simpan perubahan
Pertanyaan saya adalah skenario berikut, apa yang akan terjadi jika:
Di ProductService.ChangeProductGroup, kami memeriksa grup yang ada (memang ada), lalu tepat setelah pemeriksaan ini pengguna yang terpisah menghapus productGroup (melalui GroupService.DeleteGroup lainnya). Dalam hal ini kami menetapkan referensi ke produk yang baru saja dihapus?
Apakah ini cacat dalam desain saya karena saya harus menggunakan desain domain yang berbeda (menambahkan elemen tambahan jika perlu), atau apakah saya harus menggunakan transaksi?
sumber
Mengapa Anda tidak menyimpan id produk di entitas Grup? Dengan cara ini Anda hanya berurusan dengan satu agregat yang akan membuat segalanya lebih mudah.
Anda kemudian perlu menerapkan beberapa jenis pola konkurensi mis. Jika Anda memilih konkurensi optimis cukup tambahkan properti versi ke entitas Grup dan berikan pengecualian jika versi tidak cocok saat memperbarui yaitu
Tambahkan produk ke grup
Banyak ORM memiliki konkurensi optimis bawaan menggunakan id versi atau cap waktu tetapi mudah untuk menggulirkan Anda sendiri. Berikut adalah posting yang bagus tentang bagaimana hal ini dilakukan di Nhibernate http://ayende.com/blog/3946/nhibernate-mapping-concurrency .
sumber
Meskipun transaksi mungkin membantu, ada cara lain, terutama jika skenario Anda terbatas hanya pada beberapa kasus.
Anda dapat menyertakan pemeriksaan dalam kueri yang melakukan mutasi, secara efektif menjadikan setiap pasangan periksa dan mutasi sebagai operasi atom.
Bagian dalam permintaan pembaruan produk bergabung dengan grup (baru direferensikan). Ini menyebabkannya tidak memperbarui apa pun jika grup itu hilang.
Kueri penghapusan grup bergabung dengan produk yang menunjuk ke sana dan memiliki kondisi tambahan bahwa (salah satu kolom) hasil gabungan harus nol. Ini menyebabkannya tidak menghapus apa pun jika ada produk yang menunjukkannya.
Kueri mengembalikan jumlah baris yang cocok atau diperbarui. Jika hasilnya 0, maka Anda kehilangan kondisi balapan dan tidak melakukan apa pun. Itu bisa melempar pengecualian, dan lapisan aplikasi dapat menangani yang diinginkan, seperti dengan mencoba lagi dari awal.
sumber