เท่าที่ฉันเข้าใจแนวคิดที่สำคัญเบื้องหลัง CQRS คือมีตัวแบบข้อมูล 2 แบบสำหรับจัดการคำสั่งและแบบสอบถาม สิ่งเหล่านี้เรียกว่า "write model" และ "read model"
ลองพิจารณาตัวอย่างของการโคลนใบสมัคร Twitter นี่คือคำสั่ง:
- ผู้ใช้สามารถลงทะเบียนด้วยตนเอง
CreateUserCommand(string username)
ส่งเสียงUserCreatedEvent
- ผู้ใช้สามารถติดตามผู้ใช้รายอื่น
FollowUserCommand(int userAId, int userBId)
ส่งเสียงUserFollowedEvent
- ผู้ใช้สามารถสร้างโพสต์
CreatePostCommand(int userId, string text)
ส่งเสียงPostCreatedEvent
ขณะที่ฉันใช้คำว่า "เหตุการณ์" ด้านบนฉันไม่ได้หมายถึงเหตุการณ์ 'การจัดหากิจกรรม' ฉันแค่หมายถึงสัญญาณที่ทริกเกอร์อ่านการอัพเดตโมเดล ฉันไม่มีที่เก็บเหตุการณ์และจนถึงตอนนี้ต้องการที่จะมีสมาธิกับ CQRS เอง
และนี่คือแบบสอบถาม:
- ผู้ใช้ต้องเห็นรายการโพสต์
GetPostsQuery(int userId)
- ผู้ใช้ต้องการดูรายชื่อผู้ติดตาม
GetFollowersQuery(int userId)
- ผู้ใช้ต้องการดูรายชื่อผู้ใช้ที่ติดตาม
GetFollowedUsersQuery(int userId)
- ผู้ใช้ต้องการเห็น "ฟีดเพื่อน" - บันทึกกิจกรรมของเพื่อนทั้งหมด ("เพื่อนของคุณจอห์นเพิ่งสร้างโพสต์ใหม่")
GetFriedFeedRecordsQuery(int userId)
เพื่อจัดการCreateUserCommand
ฉันจำเป็นต้องรู้ว่าผู้ใช้ดังกล่าวมีอยู่แล้ว ดังนั้น ณ จุดนี้ฉันรู้ว่ารูปแบบการเขียนของฉันควรมีรายชื่อผู้ใช้ทั้งหมด
ในการจัดการFollowUserCommand
ฉันจำเป็นต้องรู้ว่า userA ติดตาม userB อยู่แล้วหรือไม่ ณ จุดนี้ฉันต้องการให้โมเดลการเขียนของฉันมีรายการการเชื่อมต่อที่ผู้ใช้ติดตามผู้ใช้ทั้งหมด
และในที่สุดการจัดการCreatePostCommand
ฉันไม่คิดว่าฉันต้องการอะไรอีกแล้วเพราะฉันไม่มีคำสั่งเช่นUpdatePostCommand
นั้น หากฉันมีสิ่งเหล่านั้นฉันจะต้องตรวจสอบให้แน่ใจว่ามีโพสต์อยู่แล้วดังนั้นฉันจะต้องมีรายการโพสต์ทั้งหมด แต่เนื่องจากฉันไม่มีข้อกำหนดนี้ฉันจึงไม่จำเป็นต้องติดตามโพสต์ทั้งหมด
คำถาม # 1 : จริง ๆ แล้วใช้คำว่า "แบบจำลองการเขียน" ถูกต้องหรือไม่ หรือ "การเขียนแบบ" มักจะยืนสำหรับ "ที่จัดเก็บเหตุการณ์" ในกรณีของ ES หรือไม่? ถ้าเป็นเช่นนั้นจะมีการแบ่งแยกระหว่างข้อมูลที่ฉันต้องการจัดการคำสั่งและข้อมูลที่ฉันต้องการในการจัดการแบบสอบถามหรือไม่?
ในการจัดการGetPostsQuery
ฉันต้องการรายการโพสต์ทั้งหมด ซึ่งหมายความว่าโมเดลการอ่านของฉันควรมีรายการโพสต์ทั้งหมด PostCreatedEvent
ฉันจะรักษารูปแบบนี้โดยการฟัง
เพื่อจัดการทั้งสองGetFollowersQuery
และGetFollowedUsersQuery
ฉันจะต้องมีรายการการเชื่อมต่อทั้งหมดระหว่างผู้ใช้ UserFollowedEvent
เพื่อรักษารูปแบบนี้ฉันจะฟัง นี่คือคำถาม # 2 : มันใช้ได้จริงไหมถ้าฉันใช้รายชื่อการเชื่อมต่อของแบบจำลองการเขียนที่นี่? หรือฉันควรสร้างแบบจำลองการอ่านแยกต่างหากเพราะในอนาคตฉันอาจต้องมีรายละเอียดมากกว่าแบบจำลองการเขียน?
ในที่สุดการจัดการGetFriendFeedRecordsQuery
ฉันจะต้อง:
- ฟัง
UserFollowedEvent
- ฟัง
PostCreatedEvent
- รู้ว่าผู้ใช้คนใดที่ติดตามผู้ใช้คนอื่น
หากผู้ใช้กตามผู้ใช้ขและผู้ใช้ขเริ่มติดตามผู้ใช้คเรกคอร์ดต่อไปนี้ควรปรากฏขึ้น:
- สำหรับผู้ใช้ A: "คุณเป็นเพื่อนผู้ใช้ B เพิ่งเริ่มติดตามผู้ใช้ C"
- สำหรับผู้ใช้ B: "คุณเพิ่งเริ่มติดตามผู้ใช้ C"
- สำหรับผู้ใช้ C: "ผู้ใช้ B กำลังติดตามคุณ"
นี่คือคำถาม # 3 : ฉันควรใช้รุ่นใดเพื่อรับรายการการเชื่อมต่อ ฉันควรใช้แบบจำลองการเขียนหรือไม่? ฉันควรใช้แบบอ่าน - GetFollowersQuery
/ GetFollowedUsersQuery
? หรือฉันควรสร้างGetFriendFeedRecordsQuery
แบบจำลองเองจัดการUserFollowedEvent
และดูแลรายการการเชื่อมต่อทั้งหมดของตัวเอง?