مقدمه CQRS یک الگوی معماری است که از کنار هم قرار دادن حروف اول عبارت Command Query Responsibility Segregation تشکیل شده است. این الگو، عملیات سیستم را به دو قسمت دستورات ( Commands ) و کویری ها ( Queries ) تقسیم بندی می کند. CQRS با CQS که مخفف Command Query Separation است مرتبط بوده و از آن مشتق شده است. در این پست، ابتدا CQS را تعریف کرده و ارتباط آن با CQRS را بررسی می کنیم. سپس به توضیح CQRS می پردازیم و در ادامه اصول اصلی، مزایا و همچنین برخی از تصورات اشتباه در مورد این الگو را بررسی می کنیم. CQS چیست؟ CQS یک الگوی طراحی است که از کنار هم قرار دادن حروف اول عبارت Command Query Separation تشکیل شده است. CQS یک مفهوم اولیه و اساسی است که برای عملیات انجام شده بر روی سیستم، دو نوع را تعریف می کند: دستوری که یک تسک را اجرا می کند و کویری که اطلاعاتی را برمی‌گرداند، و تابعی نباید وجود داشته باشد که هر دوی این کارها را انجام دهد. این اصطلاح توسط و در کتاب "ساخت نرم افزار شی گرا" در سال خلق شد او آن را به عنوان بخشی از کار خود بر روی زبان برنامه نویسی ایجاد کرد. CQRS اصل تعیین کننده CQS را می گیرد و آن را به اشیا ء خاصی در سیستم گسترش می دهد، یکی در بازیابی داده و دیگری در تغییر داده. CQRS یک الگوی معماری گسترده و CQS ، یک اصل عمومی رفتاری است. CQRS چیست؟ CQRS تفکیک مسیولیت های دستورات و کویری ها در یک سیستم است. این بدان معناست که ما منطق برنامه خود را به صورت عمودی برش می دهیم. علاوه بر این، پرش حالت (دستورالعمل فرمان) را از بازیابی اطلاعات (کنترل کویری) جدا می کنیم. CQRS توسط Greg Young تعریف شد. "اشیا" در تعریف اصلی، با ذخیره سازی ( Storage ) مرتبط نبوده بلکه با کنترل کننده ها ( Handlers ) مرتبط هستند. ما خطوط لوله ( Pipelines ) مختلفی را برای رفتار های تجاری متفاوت ایجاد می کنیم، نه برای ذخیره سازی جداگانه. اصول اصلی اصل اساسی CQRS ، جداسازی دستورات و کویری ها و کارهایی است که آن ها انجام می دهند. دستورات و کویری ها، نقش‌های بسیار متفاوتی را در یک سیستم انجام می‌دهند و تفکیک آنها به این معنی است که هر کدام می‌توانند در صورت نیاز بهینه شوند که می‌تواند برای سیستم‌های توزیع‌شده بسیار مفید باشد. Alexey Zimarev ، چگونگی تفاوت دستورات و کویری ها را به صورت زیر تعریف کرده است: در ادامه، به دستورات، کویری ها و ارتباط آن ها با مدل های خواندن ( Read ) و نوشتن ( Write ) ، می پردازیم. دستورات ( Commands ) به گفته برتراند مایر، Command یک فرمان است دستوری برای انجام یک کار خاص که قصد دارد چیزی را تغییر دهد. یک دستور باید هدف کاربر را منتقل کند. طبق توضیح الکسی زیمارف، اجرای یک دستور باید منجر به یک تراکنش روی یک جمع شود. اساسا ، هر دستور باید به وضوح یک تغییر کاملا تعریف شده را بیان کند. دستورات، مدل نوشتن ( Write Model ) را تشکیل می دهند و مدل نوشتن باید تا حد امکان به فرآیندهای تجاری نزدیک باشد. کویری ها ( Queries ) به گفته برتراند مایر، کویری، یک درخواست برای اطلاعات است. کویری، درخواستی برای دریافت اطلاعات و یا وضعیت اطلاعات از یک مکان مشخص است. هیچ چیزی در داده ها نباید با درخواست تغییر کند. از آنجایی که کویری ها چیزی را تغییر نمی دهند، نیازی به درگیر کردن مدل دامنه ( Domain Model ) ندارند. کویری ها مدل خواندن ( Read Model ) را تشکیل می دهند. مدل خواندن باید از مدل نوشتن مشتق شود. همچنین لازم نیست دایمی باشد. مدل‌های خواندن جدید را می‌توان بدون ت ثیرگذاری بر مدل‌های موجود، به سیستم معرفی کرد. مدل های خواندن را می توان بدون از دست دادن منطق تجاری و یا اطلاعات، حذف و دوباره ایجاد کرد زیرا در مدل نوشتن ذخیره می شوند. مزایای CQRS استفاده از اصول CQRS در معماری، مزایای بسیاری را به همراه خواهد داشت: راهنمایی به خصوصی در مورد ساخت برنامه در رابطه با رفتار، ارایه می دهد. کد و معماری، بر اساس عملیات تجاریشان تفکیک شده اند و این کار، تمرکز بر روی مورد تجاری را آسان تر می کند. منطق، مسنجم بوده و بخش های مختلف آن، کمتر به هم مرتبط هستند و در نتیجه، ایجاد برنامه های ماژولار و قابل نگهداری را آسان تر می شود. به دلیل جداسازی عمودی، کد های مرتبط، در کنار هم نگه داشته می شوند. برای تغییر کد موجود و یا ایجاد کد جدید، نیازی به فهم تمام معماری و منطق تجاری نیست و در نتیجه، تمرکز بر روی یک وظیفه خاص، آسان تر می شود. از آن جایی که کد ما در سیلو ها نگهداری می شود، تنظیم دقیق تنها یک پایپ لاین و دست نزدن به بقیه آن ها، آسان تر است و در نتیجه، تمرکز بر روی بهینه سازی های دقیق، در مکان هایی که Business - critical هستند را آسان تر می کند. به علت جداسازی، شما قوانین عمومی ای برای رفتار عملیات دارید و از تغییر حالت برنامه به وسیله یک کویری، متعجب نمی شوید حفظ جداسازی بین منطق نوشتن و خواندن، احتمال تولید یک کد اسپاگتی را کاهش می دهد. موارد استفاده از CQRS از الگوی CQRS در موارد زیر استفاده می شود: رابط های کاربری مبتنی بر وظیفه ( Task - based user interfaces ) که در آن کاربران از طریق یک فرآیند پیچیده به عنوان یک سری مراحل یا با مدل های دامنه پیچیده هدایت می شوند. مدل نوشتن دارای یک پشته پردازش کامل فرمان ( full command - processing stack ) با منطق تجاری، اعتبارسنجی ورودی و اعتبارسنجی تجاری است. مدل نوشتن ممکن است مجموعه‌ای از اشیاء مرتبط را به‌عنوان یک واحد یکتا برای تغییر دیتا در نظر بگیرد و اطمینان حاصل کند که این اشیاء همیشه در یک حالت ثابت هستند. مدل خواندن، هیچ منطق تجاری یا پشته اعتبار سنجی ندارد و فقط یک DTO را برای استفاده در یک view model برمی گرداند. مدل خواندن در نهایت با مدل نوشتن سازگار است. دامنه های مشارکتی که در آن بسیاری از کاربران به طور موازی به داده های مشابه دسترسی دارند CQRS به شما اجازه می دهد تا دستوراتی را با جزییات کافی برای به حداقل رساندن تضادهای ادغام ( Merge conflicts ) در سطح دامنه، تعریف کنید و تداخل هایی که به وجود می آیند را با دستور ( Command ) ادغام کنید. سناریوهایی که در آن ها عملکرد خواندن داده ها باید جدا از عملکرد نوشتن داده ها تنظیم شود، به خصوص زمانی که تعداد خواندن ها بسیار بیشتر از تعداد نوشتن ها باشد در این سناریو می توانید مدل خواندن را کوچک کرده و مدل نوشتن را فقط در چند نمونه اجرا کنید. تعداد کمی از نمونه های مدل نوشتن نیز به حداقل رساندن وقوع تضادهای ادغام کمک می کنند. سناریوهایی که در آن یک تیم از توسعه دهندگان می تواند بر روی مدل دامنه پیچیده که بخشی از مدل نوشتن است تمرکز کرده و تیم دیگری می تواند بر روی مدل خواندن و رابط های کاربری تمرکز کند. سناریوهایی که در آن ها انتظار می‌رود سیستم در طول زمان تکامل یابد و ممکن است چندین نسخه از مدل را شامل شود یا سناریو هایی که در آن ها، قوانین تجاری به طور منظم تغییر می‌کنند. ادغام با سایر سیستم ها به ویژه در ترکیب با الگوی منبع رویداد که در آن خرابی موقت یک زیرسیستم نباید بر در دسترس بودن سایر زیر سیستم ها ت ثیر بگذارد. الگوی CQRS برای موارد زیر، توصیه نمی شود: دامنه یا قوانین تجاری ساده هستند. یک رابط کاربری ساده به سبک CRUD : عملیات دسترسی به داده کافی است. استفاده از CQRS را به بخش هایی از سیستم خود محدود کنید که در آن ها بیشترین ارزش را خواهد داشت. چالش ها برخی از چالش های استفاده از این الگو، عبارتند از: ایده اصلی CQRS ساده است، اما می تواند منجر به پیچیدگی طراحی برنامه شود، به خصوص اگر شامل الگوی Event Sourcing باشد. اگرچه CQRS به پیام رسانی نیازی ندارد، استفاده از پیام رسانی برای پردازش دستورات و انتشار به روز رسانی ها معمول است. در این صورت، برنامه باید با دو مشکل خرابی پیام ها و پیام های تکراری مقابله کند. اگر پایگاه های داده خواندن و نوشتن را از هم جدا کنید، داده های خوانده شده ممکن است کهنه شود. مخزن مدل خواندن باید به روز شود تا تغییرات را در مخزن مدل نوشتن منعکس کند و تشخیص این که کاربر بر اساس داده های خوانده شده قدیمی، یک درخواست را انجام داده است، می تواند دشوار باشد. تصورات غلط در مورد CQRS این عبارت، لزوما درست نیست فقط نیاز است که رفتار ها و مسیولیت های آن دو را از هم جدا کرد. این می تواند داخل کد، در ساختار یک پایگاه داده و یا پایگاه های داده مختلف باشد. CQRS حتی نیازی به استفاده از پایگاه داده ندارد ممکن است از اکسل و یا هر چیز دیگر که حاوی داده است، استفاده شود. CQRS ، برای رفتار یک سیستم کاربرد دارد، نه برای مکان ذخیره سازی داده. به خاطر داشته باشید که جمله کلیدی " CQRS به رفتار اشاره دارد و نه ذخیره سازی"، کلید استفاده موثر از CQRS است. جداسازی دستورات و کویری ها و مدیریت متفاوت آنها می تواند یک سیستم در نهایت سازگار را تولید کند. این تصور غلط وجود دارد که سیستم های درنهایت سازگار به دلیل تاخیرهای زمانی، دقیق نبوده و با جداسازی دستورات و کویری ها در CQRS ، باید تاخیر ها و در نتیجه مشکلات سازگاری نهایی وجود داشته باشد. صف های پیام مانند Kafka و RabbitMQ ، بسته به شرایط به شما امکان ارسال پیام بین مدل های خواندن و نوشتن را می دهند. اگر مدل شما ساده بوده و با نماهای مختلف پایگاه داده شروع می شود، به صف های پیام نیازی نیست به طور کلی، استفاده از آن، به نیازمان در آن زمینه تجاری خاص، بستگی دارد. ساخت سیستم با در نظر گرفتن CQRS به شما این امکان را می دهد که انواع مختلف پایگاه های داده را در تعامل با یکدیگر داشته باشید. صف های پیام رسانی برای نگه داری به روز مدل های خواندن در صورت تغییر مدل نوشتن، مفید خواهند بود. "فقط می تواند با DDD استفاده شود. " CQRS و DDD نسبت به هم، دو مفهوم مجزا و متعامد هستند و برای استفاده از DDD نیازی به استفاده از CQRS نیست و برعکس. DDD در اصل با CQRS هماهنگ است اما این دو قطعا به یکدیگر وابسته نیستند. جمع بندی الگوی معماری CQRS ، روشی برای جداسازی رفتار نوشتن و خواندن داده‌ها از یکدیگر است. این روش، برای سیستم‌هایی که با تعداد درخواست‌های بسیار زیادی روی پایگاه‌های داده خود مواجه هستند مناسب است. CQRS در شرایط مناسب، باعث افزایش کارایی سیستم‌و مقیاس پذیری بهتر آن می شود. لازم به ذکر است که استفاده از CQRS آسان نبوده و نیاز به نیروی متخصص دارد. جداسازی مدل‌های خواندن و نوشتن از یکدیگر، خطر ایجاد ناهماهنگی میان داده‌ها را بالا می برد بنابراین از CQRS باید در موارد کاربردی خود و به طور سنجیده استفاده شود. "این مطلب، بخشی از تمرینهای درس معماری نرم‌افزار در دانشگاه شهیدبهشتی است. " مراجع این وبسایت : bertrandmeyer . com این وبسایت : www . eiffel . com / resources / faqs / eiffel - language این وبسایت : www . eventstore . com / cqrs - pattern این وبسایت : martinfowler . com / bliki / CQRS . html این وبسایت : docs . microsoft . com / en - us / azure / architecture / patterns / cqrs