Sejauh yang saya mengerti, ide besar di balik CQRS adalah memiliki 2 model data yang berbeda untuk menangani perintah dan permintaan. Ini disebut "model tulis" dan "model baca".
Mari kita perhatikan contoh klon aplikasi Twitter. Berikut adalah perintahnya:
- Pengguna dapat mendaftar sendiri.
CreateUserCommand(string username)
memancarkanUserCreatedEvent
- Pengguna dapat mengikuti pengguna lain.
FollowUserCommand(int userAId, int userBId)
memancarkanUserFollowedEvent
- Pengguna dapat membuat posting.
CreatePostCommand(int userId, string text)
memancarkanPostCreatedEvent
Sementara saya menggunakan istilah "acara" di atas, saya tidak bermaksud acara 'sumber acara'. Maksud saya sinyal yang memicu pembaruan model baca. Saya tidak punya toko acara dan sejauh ini ingin berkonsentrasi pada CQRS sendiri.
Dan inilah pertanyaannya:
- Seorang pengguna perlu melihat daftar postingannya.
GetPostsQuery(int userId)
- Seorang pengguna perlu melihat daftar pengikutnya.
GetFollowersQuery(int userId)
- Seorang pengguna perlu melihat daftar pengguna yang diikuti.
GetFollowedUsersQuery(int userId)
- Seorang pengguna perlu melihat "umpan teman" - log dari semua aktivitas teman mereka ("teman Anda John baru saja membuat posting baru").
GetFriedFeedRecordsQuery(int userId)
Untuk menangani CreateUserCommand
saya perlu tahu apakah pengguna seperti itu sudah ada. Jadi, pada titik ini saya tahu bahwa model penulisan saya harus memiliki daftar semua pengguna.
Untuk menangani FollowUserCommand
saya perlu tahu apakah userA sudah mengikuti userB atau tidak. Pada titik ini saya ingin model tulis saya memiliki daftar semua koneksi pengguna-mengikuti-pengguna.
Dan akhirnya, untuk menangani CreatePostCommand
saya tidak berpikir saya perlu yang lain, karena saya tidak punya perintah seperti UpdatePostCommand
. Jika saya punya itu, saya perlu memastikan bahwa posting ada, jadi saya perlu daftar semua posting. Tetapi karena saya tidak memiliki persyaratan ini, saya tidak perlu melacak semua posting.
Pertanyaan # 1 : apakah benar menggunakan istilah "model tulis" seperti yang saya gunakan? Atau apakah "menulis model" selalu berarti "event store" untuk ES? Jika demikian, apakah ada jenis pemisahan antara data yang saya butuhkan untuk menangani perintah dan data yang saya butuhkan untuk menangani pertanyaan?
Untuk menangani GetPostsQuery
, saya perlu daftar semua posting. Ini berarti bahwa model baca saya harus memiliki daftar semua posting. Saya akan mempertahankan model ini dengan mendengarkan PostCreatedEvent
.
Untuk menangani keduanya GetFollowersQuery
dan GetFollowedUsersQuery
, saya perlu daftar semua koneksi antara pengguna. Untuk mempertahankan model ini saya akan mendengarkan UserFollowedEvent
. Berikut adalah Pertanyaan # 2 : apakah bisa dibilang OK jika saya menggunakan daftar koneksi model tulis di sini? Atau haruskah saya membuat model baca yang lebih baik, karena di masa depan saya mungkin memerlukannya untuk memiliki lebih banyak detail daripada model tulis?
Akhirnya, untuk menangani GetFriendFeedRecordsQuery
saya perlu:
- Mendengarkan
UserFollowedEvent
- Mendengarkan
PostCreatedEvent
- Ketahui pengguna mana yang mengikuti pengguna lain
Jika pengguna A mengikuti pengguna B dan pengguna B mulai mengikuti pengguna C, catatan berikut ini akan muncul:
- Untuk pengguna A: "Anda teman pengguna B baru saja mulai mengikuti pengguna C"
- Untuk pengguna B: "Anda baru saja mulai mengikuti pengguna C"
- Untuk pengguna C: "Pengguna B sekarang mengikuti Anda"
Inilah Pertanyaan # 3 : model apa yang harus saya gunakan untuk mendapatkan daftar koneksi? Haruskah saya menggunakan model tulis? Haruskah saya menggunakan model baca - GetFollowersQuery
/ GetFollowedUsersQuery
? Atau haruskah saya membuat GetFriendFeedRecordsQuery
model itu sendiri menangani UserFollowedEvent
dan mempertahankan daftar semua koneksi sendiri?