Masoud Ghiasi
Masoud Ghiasi
خواندن ۴ دقیقه·۲ سال پیش

CQRS هیچگاه پرسش باعث تغییر نمی شود و صرفا دستورات باعث ایجاد تغییرات می شوند

CQRS

هیچگاه پرسش باعث تغییر نمی شود و صرفا دستورات باعث ایجاد تغییرات می شوند

CQRS چیست؟

این کلمه مخفف الگوی معماری از Command-Query responsibility segregation است به معنی جداسازی مسئولیت پرسش و فرمان است. به این صورت که درخواست های نوشتن و درخواست های خواندن توسط مدل های (اشیا) مختلفی اجرا میشوند.

این الگو اولین بار توسط Greg young معرفی شده است.

CQS چیست؟

این الگوی طراحی مخفف Command-Query Segregation است و به این معنی است در سیستم اعمال صرفا دو نوع هستند، یک متد یا یک عمل را انجام می دهد و یا پرسشی که داده ای بر میگرداند و فقط یکی از این دو کار را انجام میدهد نه هر دو.

دستورات: صرفا عملی را انجام میدهند و بازگشت آنها void است.

پرسش ها: در مقابل پرسش ها هیچ اثر جانبی از خود به جای نمی گذارند و صرفا بازگشت اطلاعات را دارند.

این مفهوم در اصل صرفا بازگشت متد تمرکز دارد و تفاوت در نظر میگیرد و اکثرا به خوبی قابل اجراست اما استثناهایی هم دارد.

به طور مثال

  1. در iterate کردن زبان جاوا مجموعه ها با تابع next، که مزیت اصلی همین تابع است که مقدار را برمی گرداند و اثر جانبی حذف را دارد.
  2. در پیاده سازی پشته (Stack) که pop کردن نیز اثر جانبی دارد.

این الگوی اولین بار توسط Bertrand Meyer در کتاب Object-oriented Software Construction معرفی شد. Bertrand یکی از سازندگان زبان برنامه نویسی Eiffel است.

اثر جانبی چیست؟

یک اثر جانبی زمانی اتفاق می افتد که یک تابع بر روی چیزی خارج از پارامترهای ورودی خود تغییری ایجاد کند مثل چیزی چاپ کند یا مقداری را از فایل، دیتابیس یا متغیری را تغییر دهد.

تفاوت CQS و CQRS چیست؟

CQS دستورات و پرس و جوها را به روش های مختلف در یک نوع قرار می دهد.

CQRS دستورات و پرس و جوها را روی اشیاء مختلف قرار می دهد.

مشکل چیست؟

در سیستم هایی که از ساختار CRUD استفاده می کنند به سادگی برای ما ایجاد، ویرایش، حذف و خواندن موجودیت ها را فراهم می کند. اما زمانی که یک پاسخ پرسش نیاز به تجمیع چند پرسش دیگر دارد باید چکار کنیم؟

عموما خواندن اطلاعات و بازگشت آن ها با اشکال مختلف نیازمند زمان پردازش کمتری نسبت به ایجاد، ویرایش و حذف کردن اطلاعات دارد و نیازمند پیچیدگی های اعتبارسنجی، منطق بیزینس یا دسترسی نیست.

خواندن اطلاعات: واکشی اطلاعات و بازگشت در اشکال مختلف DTOs یا Data Transfer Objects

افزودن، ویرایش و حذف: اعتبارسنجی ورودی، بررسی دسترسی امنیتی و مجوزها، بررسی منطق بیزینسی و …

این تفاوت ها اختلاف زمانی و پردازشی متفاوتی دارند.

کجا استفاده کنیم؟

در بخش هایی قابل استفاده است که اختلاف قابل توجهی در پردازش و زمان اجرا در خواندن و ویرایش اطلاعات باشد.

  • در واکشی اطلاعات کاربران نیاز داریم امتیاز کاربران را داشته باشیم
  • در واکشی سبد خرید بدانیم شامل چه محصولاتی است و یا در واکشی محصولات بدانیم که هر محصول چه تخفیف هایی دارد
  • در یک واکشی فرضی برای صفحه ای سمت پشتیبانی نیاز داشته باشیم اطلاعات یک کاربر را همراه اعتبار، سفارشات به همراه محصولاتشان و پیامی که کاربر داده را نمایش دهیم

راه حل چگونه است؟

راه حل ارائه شده توسط الگوی معماری CQRS این است که مدل خواندن و نوشتن را از یکدیگر جدا کنیم و با استفاده از دستورات اطلاعات را به روز کنیم و با پرسش ها آنها را بخوانیم.


دستورات صرفا باید تسک محور باشند و اثر جانبی نیز نداشته باشند.

پرسش ها صرفا اطلاعات را به اشکال مختلف برگردانند.

در مدلی که برای خواندن استفاده می شود میتوانیم آبجکت های پیچیده ای که از جاهای مختلف ترکیب می شوند را به مدل های جداگانه ای برای به روز رسانی و نمایش تقسیم کنیم و برای نمایش آن را به صورت آماده در دیتابیس NoSql ذخیره کنیم و دیگر برای گرفتن آنها نیازی به انجام عملیات های پیچیده نداریم و علاوه بر آن سرعت این واکشی به دلیل پردازش که از قبل انجام شده کاهش دهیم.

این الگو اجازه ی مقیاس پذیری هم بر اساس باری که روی هر بخش است را نیز میدهد.

مزیت ها:

  • مقیاس پذیری مستقل خواندن نوشتن. میتوایم خواندن را از کپی های پایگاه داده انجام دهیم.
  • بهینه سازی ساختارها. می توان ساختارهای که برای واکشی استفاده می شود را به طور اختصاصی بهینه کرد و ساختار دیتا برای نوشتن را مختص ویرایش اطلاعات بهینه کرد.

نکات استفاده

زمانی که از مدل های متفاوتی برای خواندن و نوشتن استفاده می شود باید اطلاعات همگام باشند که این کار معمولا با انتشار یک رویداد توسط مدل نوشتن هر زمان پایگاه داده به روز می کند، انجام می شود.

ممکن است نیاز باشد تا دستورات در صف هایی مانند RabbitMQ یا Kafka یا NATS قرار بگیرند تا بتوان آن ها را موازی پردازش کرد.

استفاده از این الگو صرفا باید شامل بخش های مشخصی از سیستم باشد و نه در کل سیستم. عملکرد و تصمیم گیری هر بخش باید بسته به نیازمندی آن بخش باشد.

هنگامی باید از این الگو استفاده شود که تفاوت زیادی بین خواندن و نوشتن باشد و راه کارهای بهینه سازی پاسخگو نباشد.

با توجه تجربه در نوشتن نرم افزار های مختلف نباید در زمان توسعه نرم افزار قبل از اینکه نیاز به افزایش سرعت باشد پیچیدگی را در نرم افزار زیاد کنید.

مقیاس پذیرینرم افزارcqrsdesign patternevent sourcing
مسعود غیاثی
شاید از این پست‌ها خوشتان بیاید