หลัง ๆ มาในโลกการพัฒนา Software มักได้ยินคำแปลก ๆ ออกมาเยอะมาก
(ตามจริงอาจจะไม่แปลก แต่เราไม่เคยรู้มากกว่า )
หนึ่งในนั้นคือแนวคิด CQRS (Command Query Responsibility Segregation)
โดยแนวคิดนี้มันจะพ่วงมาจากเรื่องของ DDD (Domain-Driven Design) และ Microservices
หนักกว่านั้นโยงไปถึง Event sourcing อะไรพวกนั้นอีก
ทำให้งงเข้าไปใหญ่
ดังนั้นเพื่อความไม่สับสนจึงลองไปศึกษาหน่อยว่า
จริง ๆ แล้วแนวคิดนี้มันมีที่มาที่ไปอย่างไร ?

เรื่องแรก ถ้าเราไปค้นหาใน Google น่าจะเจอ link เหล่านี้

เยอะไปไหน !!!

ต่อมาก็ลงไปหาที่มาของแนวคิดนี้จาก CQRS Info
ก็ได้ paper ของแนวคิดมาคือ

ก็ทำให้รู้และเข้าใจที่มาของแนวคิด CQRS ว่าเป็นดังนี้

จุดเริ่มต้นของแนวคิด CQRS ?

เริ่มจาก design pattern ซึ่งหน้าที่การทำงานของ class ต่าง ๆ มักจะประกอบไปด้วย

  • Query คือการดึงข้อมูล
  • Command คือการเปลี่ยนแปลงทั้งการเพิ่ม ลบและแก้ไข

จากหนังสือ Object-Oriented Software Construction เขียนไว้ว่า

Every method should either be a command that performs an action,
or a query that returns data to the caller,
but not both.

In other words,
Asking a question should not change the answer.

พูดง่าย ๆ มันคือเราควรแยกการทำงานทั้งคู่ออกจากกัน 
หรือเรียกว่า Command Query Separation
คิดโดย Bertrand Meyer ซึ่งอธิบายไว้ว่า

  • Query ทำการ return ข้อมูลกลับมา โดยไม่ทำการเปลี่ยนแปลงข้อมูลใด ๆ หรือไม่มี side-effect นั่นเอง หรือเรียกว่า pure function ก็ได้
  • Command ทำการเปลี่ยนแปลงข้อมูล แต่ไม่ return ข้อมูลกลับมา

ซึ่งการนำแนวคิดนี้ไปประยุกต์ใช้มันมีหลายระดับหรือขอบเขตมาก ๆ
ทั้งระดับ class/method, service, database และ system เป็นต้น
เป็นเรื่องของการแบ่งหน้าที่รับผิดชอบกัน (Single Responsibility Principle)

ถ้ามองในขอบเขตของ class ในโลกของ Object-Oriented แล้ว

เราสามารถทำได้ดังนี้
ยกตัวอย่างเช่น Customer Service มีความสามารถดังนี้

  • ดึงข้อมูล customer ทั้งหมด
  • ดูข้อมูลของ customer แต่ละคน
  • ทำการสร้าง customer ใหม่
  • ทำการแก้ไข customer ที่มีอยู่
  • ทำการลบ customer ออกจากระบบ

โดยถ้าใช้แนวคิด Command Query Separation มาใช้เพื่อแยกการทำงานสามารถแบ่งได้ดังนี้

กลุ่มที่ 1 Customer Read Service

  • ดึงข้อมูล customer ทั้งหมด
  • ดูข้อมูลของ customer แต่ละคน

กลุ่มที่ 2 Customer Write Service

  • ทำการสร้าง customer ใหม่
  • ทำการแก้ไข customer ที่มีอยู่
  • ทำการลบ customer ออกจากระบบ

ดูแล้วเป็นสิ่งที่เรียบง่ายมาก ๆ ไม่น่าสนใจอะไร
แต่จริง ๆ แล้วเป็นรูปแบบที่มีประสิทธิภาพอย่างมาก
เนื่องจาก ช่วยทำให้เราแรกการออกแบบ data model ที่เหมาะสม
ต่อการทำงานทั้ง read และ write
โดยที่ data model เหล่านั้นยังคงทำงานอยู่บนข้อมูลชุดเดียวกัน
Data model ก็คือมุมมองที่มีต่อข้อมูล ซึ่งการทำงานต่างกัน มุมมองย่อมต่างกัน

เมื่อย้อนกลับมาดูแล้ว พบว่า เรามักใช้ data model ชุดเดียวกันเสมอ สำหรับทุก ๆ เรื่อง ทำไมนะ ?

มาถึงแนวคิด CQRS กันบ้าง

แน่นอนว่ามาจากแนวคิด Command Query Separation นั่นเอง
จาก VDO บอกว่า
ถ้าค้นหาคำว่า CQRS ใน google เมื่อ 10 ปีที่แล้ว
จะบอกว่าสะกดผิด และแนะนำว่าเป็นคำว่า Cars  !!

โดยที่แนวคิด CQRS นั้นไม่ใช่แนวคิดใหม่อะไร
แต่กลับได้รับความนิยมหรือพูดถึงมาก ๆ 
เมื่อมีการพูดถึง DDD, event sourcing มากขึ้น
นั่นคือมีการจัดเก็บ event ไว้ใน event store
รวมทั้ง event ต่าง ๆ เป็น immutable หรือไม่สามารถแก้ไขได้
และผลลัพธ์จะถูกสร้างมาจากการรวม event เข้าด้วยกันตามลำดับเวลาที่ event เกิดขึ้น
ฟังมาถึงตรงนี้มันคุ้น ๆ เหมือน Git เลยนะ

แนวคิด CQRS นั้นจะมีประสิทธิภาพสูงขึ้น
เมื่อทำงานร่วมกับ Event sourcing
แต่ก็ไม่ใช่คำตอบสำหรับทุก ๆ ปัญหา
ต้องเลือกใช้ให้ถูกกับปัญหาด้วย

เนื่องจากแนวคิดนี้มีข้อดีแต่ก็มีข้อเสียเช่นกัน
ยกตัวอย่างเช่น เพิ่มความซับซ้อนของระบบงานให้มากยิ่งขึ้น
ดังนั้นการจะเลือกใช้อะไรสักอย่างก็ต้องรู้ทั้งข้อดีและข้อเสีย
เพื่อจะได้เตรียมการรับมือไว้

อีกเรื่องคือ บ่อยครั้งเรามักจะสร้างระบบ Event sourcing ขึ้นมา
สำหรับการใช้งานทั้ง application นั่นคือระบบ Monolithic ของ event นั่นเอง
ซึ่งกลายเป็นภาระให้ลูกหลานต่อไปอีกแล้ว
ดังนั้นต้องระวังให้มาก

ที่สำคัญเรื่องของ Event sourcing และ CQRS นั้นยิ่งถูกพูดและใช้งานมาก ๆใน
ระบบ Cloud, Actor model และ Microservices

เมื่อพูดถึงเรื่องของ Event แล้ว ก็พ่วงไปถึงเรื่องของ Event Storming

เป็น workshop หนึ่งที่ช่วยให้เราเข้าใจ domain ของระบงานมากขึ้น
ว่ามี event และ command อะไรเกิดขึ้นบ้าง
และแต่ละ event ก่อนให้เกิดอะไรขึ้นมา ต้องการอะไรหรือกระทบอะไรบ้าง

ถ้าไม่รู้ ก็แค่ทำให้รู้ จะถูกหรือไม่ก็ลองลงมือทำในกรอบสั้น ๆ แล้วสรุปและปรับปรุงต่อไป
ขอให้สนุกกับการ coding ครับ