Bagaimana perintah Tambah / Buat * harus ditangani dalam arsitektur CQRS + Event Sourcing

11

Saya ingin menerapkan aplikasi pertama saya menggunakan pola CQRS bersama dengan Sumber Acara. Saya bertanya-tanya bagaimana pembuatan akar agregat harus ditangani dengan benar. Katakanlah seseorang mengirim perintah CreateItem. Bagaimana penanganannya? Di mana acara ItemCreated harus disimpan? Sebagai peristiwa pertama dari Item baru? Atau haruskah saya memiliki semacam entitas ItemList yang menggabungkan semua item dan daftar kejadiannya hanya terdiri dari peristiwa ItemCreated?

Udi Dahan menyarankan untuk tidak membuat akar agregat dan selalu menggunakan metode pengambilan. Tetapi bagaimana saya dapat mengambil sesuatu yang baru dan tentu saja tidak memiliki ID yang ditugaskan. Saya memahami ide di balik dan cukup masuk akal untuk berpikir bahwa objek baru adalah objek yang keadaannya terdiri dari nol peristiwa yang dijawab. Tetapi bagaimana saya harus menggunakannya? Haruskah saya memiliki metode yang berbeda dalam Repositori saya suka getNewItem()atau membuat get(id)metode saya menerima Optional<ItemId>sebagai gantinya?

Sunting: Setelah beberapa waktu penggalian, saya menemukan implementasi yang sangat menarik dari pola tersebut menggunakan aktor. Penulis bukannya membuat agregat, mengambilnya dari semacam repositori dengan UUID yang baru dibuat. Kelemahan dari pendekatan ini adalah ia memungkinkan untuk keadaan inkonsistensi sementara. Saya juga bertanya-tanya bagaimana saya bisa menerapkan deletemetode dengan pendekatan seperti itu. Cukup tambahkan acara Dihapus ke daftar acara agregat?

Mequrel
sumber
1
Saya menduga post-title Udi menyesatkan. IMHO kedengarannya seperti tujuannya yang sebenarnya adalah bahwa AR yang baru dibuat harus selalu dapat dijangkau dari beberapa tempat lain, dengan cara yang menangkap konteks tentang mengapa / bagaimana / siapa yang memutuskan bahwa AR baru perlu dibuat. Yang lainnya adalah tentang bagaimana implementasi tertentu (NHibernate?) Dapat membuatnya lebih mudah untuk dikelola.
Darien
2
Perhatikan bahwa artikel Udi Dahan yang Anda referensikan secara khusus menyebutkan bahwa sarannya mungkin tidak berlaku untuk sumber acara: udidahan.com/2009/06/29/dont-create-aggregate-roots/…
EZ Hart

Jawaban:

13

Gagasan dalam pos Udi, seperti yang saya kumpulkan, adalah bahwa tidak ada barang yang muncul karena kehabisan udara. Selalu ada (hampir) sesuatu, atau lebih khusus lagi, beberapa operasi domain, yang menyebabkan item dibuat. Sama seperti contoh Udi tentang pengguna yang sebenarnya dilahirkan dari pengunjung yang mendaftar ke situs. Pada titik itu dan pada konteks terbatas itu Pengunjung adalah akar agregat, yang diambil oleh alamat IP-nya. Pengunjung ini kemudian membuat "item" baru, seorang pengguna pada saat ini, melalui operasi domain yang disebut Daftar . Hal yang sama berlaku untuk langkah sebelumnya, yang merupakan konteks terikat lainnya: Perujuk adalah AR, yang diambil oleh URL dan yang memiliki operasi domain yang disebut BroughtVisitorWithIp , tempat pengunjung dilahirkan.

Udi menulis dengan sangat baik tentang penghapusan juga: http://www.udidahan.com/2009/09/01/dont-delete-just-dont/ . Gagasan utamanya adalah, Anda tidak pernah menghapus apa pun. Selalu ada operasi domain di belakang, yang ingin kami tangkap. Seperti pesanan dibatalkan, bukan dihapus. Baca itu, ini posting yang sangat bagus.

Poin utama di sini pada kedua akun, melakukan DDD dan terutama Event Sourcing, adalah bahwa Anda tidak boleh melakukan operasi CRUD langsung. Jika Anda menemukan diri Anda dalam situasi di mana Anda benar-benar perlu hanya menyisipkan, memperbarui atau menghapus beberapa data, dan benar-benar tidak ada operasi domain di belakangnya, maka mungkin DDD dan Pengadaan Acara tidak cocok untuk konteks yang dibatasi itu . Anda bebas untuk menggabungkan keduanya seperti yang Anda inginkan selama satu konteks terikat mematuhi satu prinsip. Dengan cara ini konteks terbatas gaya CRUD dapat membuat beberapa baris dalam database, yang menjadi entitas dan akar Agregat dalam konteks terikat lainnya, di mana Anda sekarang dapat mengambil AR dan tidak harus membuatnya.

Tuukka Haapaniemi
sumber
2
"mungkin DDD dan Event Sourcing tidak cocok untuk konteks yang dibatasi itu." Anda mendapatkan poin dari DDD dengan benar. Seharusnya tidak diterapkan dalam setiap kasus hanya untuk kemuliaan Setan tetapi hanya ketika seseorang perlu berurusan dengan domain yang kompleks penuh dengan aturan yang tidak pasti. Secara pribadi saya sudah melakukannya untuk perangkat lunak legal di mana persyaratan tidak didorong oleh logika.
Yegor Chumakov
2
+1 untuk kalimat ini saja "untuk konteks terbatas itu." :)
Songo
2
Memberi +1 penggunaan kata kerja 'Tambah' dan 'Buat' sangat menyarankan bahwa Anda masih memikirkan domain Anda dalam hal interaksi dengan database tabular lama yang baik. Tanpa mengetahui domain / konteks terbatas Anda, saya tidak dapat mengatakan apakah ini sesuai atau tidak. Abaikan kegigihan, fokus pada PERINTAH dan ACARA terlebih dahulu (alias NAMA dan HASIL) yang unik untuk domain Anda, lalu khawatir tentang cara bertahan negara, yang merupakan masalah yang telah dipecahkan ratusan ribu kali sebelumnya.
Matt
"Penggunaan kata kerja 'Tambah' dan 'Buat' sangat menyarankan bahwa Anda masih berpikir tentang domain Anda dalam hal interaksi dengan database tabel lama yang baik" Hmmm. Ketika Anda memiliki desain UI yang memiliki tombol 'Tambahkan sesuatu' besar di dalamnya, maka sayangnya, itulah tujuannya; secara harfiah menambahkan sesuatu yang baru. Saya biasanya setuju dengan Anda, tetapi kami tidak berbicara level database di sini, kadang-kadang Tambah atau Buat sebenarnya adalah kata yang tepat untuk digunakan.
designermonkey
1
@designermonkey Ketika Anda memiliki tombol-tombol di UI, apakah Anda benar-benar memiliki operasi domain di belakangnya? Mungkin, tetapi 9 dari 10 kali benar-benar tidak perlu untuk operasi domain yang kompleks pada konteks terbatas itu. Dan operasi CRUD murni hanya itu, operasi CRUD murni, dan harus ditangani seperti itu. Hanya ketika ada kebutuhan untuk kompleksitas model domain, harus digunakan. Dengan demikian konteks terikat berbeda dengan prinsip desain yang berbeda.
Tuukka Haapaniemi