ConstructiCat Logo
CodeBust.
Browse section ▾

CQRS.

Also known as — Command Query Responsibility Segregation

فصل النموذج الذي يُغيّر الحالة (الأوامر) عن النموذج الذي يقرأ الحالة (الاستعلامات)، بحيث يمكن نمذجة كل جانب وتوسيعه وتحسينه بشكل مستقل.

##Intent

استخدم نموذجًا واحدًا لتحديث المعلومات ونموذجًا مختلفًا لقراءتها. تُعبّر الأوامر عن النية في تغيير الحالة؛ وتُعيد الاستعلامات بيانات مُشكَّلة للعرض. لم يعد الطرفان بحاجة إلى التنازل على تمثيل مشترك واحد.

##Problem

في التصميم التقليدي، يخدم نموذج واحد عمليات الكتابة والقراءة كليهما. تحتاج الكتابة إلى تحقق وثوابت غنية؛ وتحتاج القراءة إلى أشكال غير معيارية وجاهزة للعرض — وكثيرًا ما تكون أشكالًا مختلفة متعددة لشاشات وتقارير مختلفة.

إجبار كليهما على المرور عبر الكائنات والجداول ذاتها يؤدي إلى تنازلات محرجة: جلب زائد، وتعيينات ORM معقدة، وتنافس على الأقفال، ونموذج لا يؤدي أيًّا من المهمتين بكفاءة.

##Solution

يقسّم CQRS النظام إلى جانبين. جانب الكتابة يعالج الأوامر عبر معالجات تحمّل تجمّعًا وتُطبّق الثوابت وتحفظ التغيير (مع إصدار أحداث اختياريًا). جانب القراءة يخدم الاستعلامات من نموذج قراءة واحد أو أكثر مُشكَّل خصيصًا للعروض التي تستهلكها.

يمكن للجانبين مشاركة قاعدة بيانات واحدة أو استخدام متاجر منفصلة. عند الفصل، تُحافَظ على نماذج القراءة محدَّثةً عبر إسقاط أحداث جانب الكتابة، بقبول الاتساق النهائي مقابل التوسع المستقل واستعلامات أبسط.

##Structure

  • الأمر — طلب لتغيير الحالة، مسمّى بحسب النية (PlaceOrder).
  • معالج الأمر — يتحقق من الأمر ويطبّقه على نموذج الكتابة.
  • نموذج الكتابة — تجمّعات تُطبّق الثوابت؛ قد تُصدر أحداثًا.
  • نموذج القراءة / الإسقاط — عروض غير معيارية مبنية للاستعلامات، تُحدَّث من الأحداث.
  • الاستعلام ومعالج الاستعلام — طلبات للقراءة فقط تُخدَّم من نموذج القراءة.

##Applicability

  • استخدمه حيث تختلف أشكال عمليات القراءة والكتابة أو أحمالها اختلافًا كبيرًا — عروض قراءة متعددة، أو تقارير مكثفة، أو نسبة قراءة إلى كتابة مرتفعة.
  • استخدمه في واجهات المستخدم القائمة على المهام والمجالات التعاونية، حيث يتكامل بشكل طبيعي مع التصميم المدفوع بالمجال ومصادر الأحداث.
  • تجنّبه في تطبيقات CRUD البسيطة؛ فالنموذج الواحد أبسط والتقسيم يُضيف تكلفة دون فائدة.

##How to Implement

  1. نمذج الأوامر كنوايا صريحة بدلًا من تحديثات عامة.
  2. وجّه كل أمر إلى معالج يحمّل التجمّع ذا الصلة ويُطبّق ثوابته.
  3. احفظ التغيير، وإذا كنت تستخدم الأحداث، انشر ما حدث.
  4. ابنِ نماذج القراءة المصمَّمة لعروضك؛ وإذا كانت منفصلة، حدّثها بإسقاط الأحداث.
  5. خدّم الاستعلامات مباشرةً من نماذج القراءة — دون منطق مجال على جانب القراءة.

##Pros & Cons

Pros
  • يمكن نمذجة جانبَي القراءة والكتابة وتحسينهما وتوسيعهما بشكل مستقل.
  • يبقى كل نموذج صغيرًا ومُركَّزًا على مهمة واحدة.
  • يتلاءم مع واجهات المستخدم القائمة على المهام ويتكامل جيدًا مع مصادر الأحداث والـ DDD.
  • يمكن تخصيص نماذج القراءة لكل عرض، مما يُلغي الضمّات المحرجة.
Cons
  • أجزاء متحركة أكثر وشيفرة أكثر مقارنةً بنموذج CRUD واحد.
  • متاجر القراءة المنفصلة تُقدّم الاتساق النهائي، والذي يجب على واجهة المستخدم التعامل معه.
  • سهل الإفراط في هندسته؛ نادرًا ما يكون مبررًا للمجالات البسيطة.
  • عبء تشغيلي لإدارة الإسقاطات وتوصيلات الرسائل.