أهلا،
شكرا لكتابة هذا المقال على CQRS. أحاول أن أفهم كيف يبدو التنفيذ وكنت أطلع على الأمثلة. يبدو رمز مستودع التخزين النموذجي المقدم في المثال مشابهًا جدًا للطريقة المعتادة لكتابة الريبو باستثناء اصطلاح التسمية. على سبيل المثال ، أعتقد أن المستودع الموضح أدناه هو نفسه ProductsCommandHandler
وربما يكون الاختلاف الوحيد هو عدم وجود GetProduct
هنا والذي نضيفه عادةً. هل يمكن أن توضح لي ما لم أحصل عليه هنا؟
public class ProductRepository {
void AddNewProduct(Product newProduct) {
...
}
void RateProduct(int productId, int userId, int rating) {
var product = repository.Find(productId);
if (product != null)
{
product.RateProduct(userId, rating);
repository.Save(product);
}
}
}
⚠ لا تقم بتحرير هذا القسم.
martinmthomas شكرا لك على سؤالك! سنراجع ونقدم تحديثًا حسب الاقتضاء.
MikeWasson أي أفكار هنا؟
AB # 160217 - شكرًا على الإبلاغ - هذه المشكلة قيد المراجعة
martinmthomas في الحقيقة معالج الأوامر ليس مستودعا. يستخدم المستودع.
يُقصد بمعالج الأوامر "معالجة الأوامر الفعلية ، إذا كان ذلك مناسبًا". في المثال ، تتلقى فئة ProductsCommandHandler
IRepository<Product>
في مُنشئها.
لنفترض أن المستخدم سيقوم بتقييم المنتج 5555 إلى 4 نجوم.
{"product":"5555","stars":4}
RateProduct
وتعبئ المنتج 5555 ، النجوم 4. في المثال ، تملأ أيضًا من هو التصنيف.CommandHandler
في وحدة التحكم الخاصة بك (ربما عن طريق إدخال التبعية) وقم فقط بوضع الأمر هناك: h.Handle (c)؛ حيث c هو الأمر RateProduct.إذن هناك 3 خيارات: أ) احصل على المعالج ، ب) احصل على قائمة الانتظار ، ج) احصل على حافلة واتركها تقرر إرسال الأمر إلى المعالج أو إلى قائمة الانتظار.
مهما كانت الطريقة التي تتبعها ... فإن الاختلاف الرئيسي حول "المستودع الكلاسيكي" هو أنك لا تستدعي المستودع نفسه في وحدة التحكم مطلقًا. المتحكم لا يعرف "كيفية إدارة الكيانات" (المستودع الكلاسيكي) ولكنه يعرف "كيفية إدارة نوايا فعل الأشياء للكيانات" (معالج الأوامر).
إذن ، معالج الأوامر هو الذي - كما يقول اسمه - "يتعامل مع الأمر" الذي جاء من مكان ما (وحدة تحكم ويب html ، وحدة تحكم API ، سطر أوامر ، أيًا كان) الذي تم إرساله كنية وهو CommandHandler (الذي ينتمي إلى جانب الكتابة) الذي يقرر ما يجب فعله بهذا الأمر.
على سبيل المثال ، يمكن لـ CommandHandler استخدام الريبو للحصول على المنتج وتعيين الحالة والحفظ (كما في المثال) ، ولكن يمكنه أيضًا الكتابة في سجل الأحداث أو تشغيل العناصر لتحديث جوانب القراءة أو تشغيل الموصلات الخارجية أو أي شيء آخر.
واجهة المستخدم المستندة إلى المهام لتقييم المنتج ووحدة التحكم الخاصة به لتكون AGNOSTIC "حيث" يتم وضع نظام النجوم / التصنيف أو تخزينه. تخيل أنك تصمم نظامًا من البداية وأن فئة المنتج تحتوي بالفعل على طريقة RateProduct () كما في المثال. حسن.
ولكن ... ماذا لو كان لديك نظام قديم هناك مع نهج "قديم" للمنتج. في "النموذج" (أي: Business Mind) لا يوجد "تصنيف" للمنتج. بدلاً من ذلك ، يريد رجل التسويق "إضافة" تصنيف إلى المنتج الحالي ولكن جميع الشركات توافق على أن هذا "شيء خارجي". هل ستستخدم مستودع المنتج؟ أو ربما تخزين مساعد آخر حتى لا "تلمس" مستودع المنتج والمنتج الذي تم اختباره بالكامل والذي تم اختباره بالكامل؟
إذا كنت تستخدم أوامر ، فإنه لا يمانع في الكتابة تحكم. سيرسل الويب و API و CLI فقط "الأمر" إلى معالج الأوامر (إما مباشرة ، عبر قائمة الانتظار أو عبر ناقل الأوامر الذي سيوجه بدوره إلى المعالج أو إلى قائمة الانتظار) وينسون. ثم سيقرر معالج الأمر ما يجب فعله باستخدام "RateProductCommand" في نقطة مركزية وصغيرة من شفرة المصدر الخاصة بك ، وهذا يفصل الطريقة التي يتم بها التعامل مع هذا من كود التطبيق ، وبالتالي يكتسب قابلية التحكم.
ثم يقرر المعالج ما إذا كان من المناسب استخدام ProductRepository أو أي طريقة أخرى لتخزين "تصنيف المنتج".
لذا ، للإجابة:
CommandHandler => ليس له علاقة بالكائنات. إنه يتعامل مع "نوايا المستخدم" (التي قد تكون في النهاية لتغيير الكيانات ؛ لذلك على الأرجح يستخدم معالج الأوامر مستودعًا).
المستودع => التخزين الفعلي لكيان معين.
نأمل في المساعدة.
تشافي.
كما ذكر xmontero ، فإن ProductsCommandHandler و
لقد قمت بتطبيق نمط تصميم CQRS في التطبيق الخاص بك ، إذا أبقيت الأوامر منفصلة عن الاستعلامات. يأخذك في اتجاه الحصول على جميع مزايا CQRS المذكورة في المقالات.
التعليق الأكثر فائدة
martinmthomas في الحقيقة معالج الأوامر ليس مستودعا. يستخدم المستودع.
يُقصد بمعالج الأوامر "معالجة الأوامر الفعلية ، إذا كان ذلك مناسبًا". في المثال ، تتلقى فئة
ProductsCommandHandler
IRepository<Product>
في مُنشئها.لنفترض أن المستخدم سيقوم بتقييم المنتج 5555 إلى 4 نجوم.
{"product":"5555","stars":4}
RateProduct
وتعبئ المنتج 5555 ، النجوم 4. في المثال ، تملأ أيضًا من هو التصنيف.CommandHandler
في وحدة التحكم الخاصة بك (ربما عن طريق إدخال التبعية) وقم فقط بوضع الأمر هناك: h.Handle (c)؛ حيث c هو الأمر RateProduct.إذن هناك 3 خيارات: أ) احصل على المعالج ، ب) احصل على قائمة الانتظار ، ج) احصل على حافلة واتركها تقرر إرسال الأمر إلى المعالج أو إلى قائمة الانتظار.
مهما كانت الطريقة التي تتبعها ... فإن الاختلاف الرئيسي حول "المستودع الكلاسيكي" هو أنك لا تستدعي المستودع نفسه في وحدة التحكم مطلقًا. المتحكم لا يعرف "كيفية إدارة الكيانات" (المستودع الكلاسيكي) ولكنه يعرف "كيفية إدارة نوايا فعل الأشياء للكيانات" (معالج الأوامر).
إذن ، معالج الأوامر هو الذي - كما يقول اسمه - "يتعامل مع الأمر" الذي جاء من مكان ما (وحدة تحكم ويب html ، وحدة تحكم API ، سطر أوامر ، أيًا كان) الذي تم إرساله كنية وهو CommandHandler (الذي ينتمي إلى جانب الكتابة) الذي يقرر ما يجب فعله بهذا الأمر.
على سبيل المثال ، يمكن لـ CommandHandler استخدام الريبو للحصول على المنتج وتعيين الحالة والحفظ (كما في المثال) ، ولكن يمكنه أيضًا الكتابة في سجل الأحداث أو تشغيل العناصر لتحديث جوانب القراءة أو تشغيل الموصلات الخارجية أو أي شيء آخر.
واجهة المستخدم المستندة إلى المهام لتقييم المنتج ووحدة التحكم الخاصة به لتكون AGNOSTIC "حيث" يتم وضع نظام النجوم / التصنيف أو تخزينه. تخيل أنك تصمم نظامًا من البداية وأن فئة المنتج تحتوي بالفعل على طريقة RateProduct () كما في المثال. حسن.
ولكن ... ماذا لو كان لديك نظام قديم هناك مع نهج "قديم" للمنتج. في "النموذج" (أي: Business Mind) لا يوجد "تصنيف" للمنتج. بدلاً من ذلك ، يريد رجل التسويق "إضافة" تصنيف إلى المنتج الحالي ولكن جميع الشركات توافق على أن هذا "شيء خارجي". هل ستستخدم مستودع المنتج؟ أو ربما تخزين مساعد آخر حتى لا "تلمس" مستودع المنتج والمنتج الذي تم اختباره بالكامل والذي تم اختباره بالكامل؟
إذا كنت تستخدم أوامر ، فإنه لا يمانع في الكتابة تحكم. سيرسل الويب و API و CLI فقط "الأمر" إلى معالج الأوامر (إما مباشرة ، عبر قائمة الانتظار أو عبر ناقل الأوامر الذي سيوجه بدوره إلى المعالج أو إلى قائمة الانتظار) وينسون. ثم سيقرر معالج الأمر ما يجب فعله باستخدام "RateProductCommand" في نقطة مركزية وصغيرة من شفرة المصدر الخاصة بك ، وهذا يفصل الطريقة التي يتم بها التعامل مع هذا من كود التطبيق ، وبالتالي يكتسب قابلية التحكم.
ثم يقرر المعالج ما إذا كان من المناسب استخدام ProductRepository أو أي طريقة أخرى لتخزين "تصنيف المنتج".
لذا ، للإجابة:
CommandHandler => ليس له علاقة بالكائنات. إنه يتعامل مع "نوايا المستخدم" (التي قد تكون في النهاية لتغيير الكيانات ؛ لذلك على الأرجح يستخدم معالج الأوامر مستودعًا).
المستودع => التخزين الفعلي لكيان معين.
نأمل في المساعدة.
تشافي.