الاستناد إلى الأحداث مقابل CRUD: استخدمه للمراجعة، وليس للجمالية_
الاستناد إلى الأحداث قوي عندما تكون التاريخية مهمة، لكنه يضيف تعقيدًا حقيقيًا. استخدمه حيث تكون القابلية للمراجعة وإعادة التشغيل متطلبات أساسية.
الاستناد إلى الأحداث يتعرض لزيادة في الطلب بطريقتين مختلفتين.
تتعامل مجموعة واحدة معه كما لو كان الطريقة الوحيدة الجادة لنمذجة أنظمة الأعمال. بينما ترفض مجموعة أخرى الأمر كتكلف معماري. كلاهما مخطئ.
يُعتبر الاستناد إلى الأحداث مبررًا عندما تكون تاريخ التغيير جزءًا من قيمة الأعمال، وليس مجرد تفصيل تنفيذي.
إذا كنت بحاجة إلى نظام إدارة محتوى مدونة أو لوحة تحكم إدارية بسيطة، فإن CRUD عادةً ما تكون التجريد الصحيح. إذا كنت تبني دفتر حسابات، أو سِلْسِلَة عمل ثقيلة للمراجعة، أو مجال حيث يكون إعادة بناء القرارات مهمًا، يصبح الاستناد إلى الأحداث خيارًا جادًا.
## الفرق الجوهري
في نموذج CRUD، الصف الحالي هو مصدر الحقيقة.
في نموذج مستند إلى الأحداث، مصدر الحقيقة هو تيار أحداث النطاق القابلة للإضافة فقط، والحالة الحالية مشتقة من تلك الأحداث.
يبدو أن هذا الاختلاف صغير على الورق. لكنه يغيّر الكثير في الممارسة.
تحديث CRUD:
```sql
UPDATE subscriptions
SET plan = 'pro', updated_at = now()
WHERE id = 'sub_123';
كتابة مستند إلى الأحداث:
{
"type": "SubscriptionUpgraded",
"subscriptionId": "sub_123",
"previousPlan": "starter",
"newPlan": "pro",
"occurredAt": "2024-03-22T05:23:50Z"
}
البيان الأول يخبرك بما هو صحيح الآن. البيان الثاني يخبرك بما حدث.
تلك التفرقة مهمة عندما تحتاج المدققون، أو فرق الدعم، أو الأنظمة التابعة إلى التسلسل، وليس فقط النتيجة.
لماذا تلجأ الفرق لذلك
تكتسب عملية الاستناد إلى الأحداث تعقيدها عندما تحتاج إلى بعض المجموعات من:
- مسار تدقيق قوي
- قابلية إعادة التشغيل
- استعلامات زمنية مثل "ماذا كنا نعتقده أمس؟"
- أحداث نطاق صريحة للمستهلكين التالين
إنها جذابة بشكل خاص عندما تكون تاريخ التغيير مفهوم أعمال من الدرجة الأولى بدلاً من أن تكون فكرة لاحقة.
لماذا تشعر الفرق بالندم
التكلفة حقيقية:
- تحتاج إلى إسقاطات لقراءات فعالة
- تطور المخطط يصبح مصدر قلق دائم
- الاتساق النهائي يصبح جزءًا من تجربة المنتج
- التصحيح التشغيلي يصبح أصعب
يمكن لنظام CRUD غالبًا أن يجيب على سؤال دعم باستعلام واحد. قد يتطلب نظام قائم على الأحداث فهم التيار، والإسقاط، وما إذا كان الإسقاط متساويًا.
لهذا السبب يجب اختيار الاستناد إلى الأحداث لأسباب تجارية، وليس لأن ذلك يبدو أكثر أناقة.
نموذج القراءة ليس اختياريًا
سجل الأحداث الصافي ليس مخزن قراءة عام جيد.
في الأنظمة الحقيقية، ينتهي الأمر بعملية الاستناد إلى الأحداث تقريبًا مع الإسقاطات أو نماذج القراءة على نمط CQRS:
type SubscriptionProjection = {
id: string;
currentPlan: string;
status: "active" | "canceled";
renewedAt: string | null;
};
async function handle(event: DomainEvent) {
switch (event.type) {
case "SubscriptionUpgraded":
await db.query(
`UPDATE subscription_projection
SET current_plan = $2
WHERE id = $1`,
[event.subscriptionId, event.newPlan],
);
break;
}
}
يحفظ تيار الأحداث التاريخ. يجعل الإسقاط النظام قابلًا للاستخدام.
الأجزاء الصعبة التي لا يمكن لأحد تخطيها
إذا اعتمدت الاستناد إلى الأحداث، فخطط لهذه من اليوم الأول:
إصدار الحدث
سيتغير فهمك للنطاق. لا يزال تحتاج إلى أن تكون الأحداث القديمة قابلة للقراءة.
المستهلكون غير القابلين للتكرار
يجب أن تتحمل المعالجات التسليم المكرر أو إعادة التشغيل.
إعادة بناء الإسقاطات
تحتاج إلى طريقة آمنة لإعادة بناء نماذج القراءة من مصدر التيار.
الرؤية التشغيلية
تحتاج إلى معرفة ما إذا كان الإسقاط جديدًا، أو متأخرًا، أو معطلاً.
لا شيء من ذلك نظري. إنها السطح التشغيلي اليومي للنظام.
قاعدة قرار مفيدة
استخدم CRUD عندما:
- تكون الحالة الحالية هي ما تهتم به الأعمال بشكل رئيسي
- يمكن التعامل مع المراجعة من خلال التسجيل التقليدي
- يكون النطاق بسيطًا ويحتوي على استعلامات كثيفة
فكر في الاستناد إلى الأحداث عندما:
- تسلسل التغيير ذو قيمة في حد ذاته
- التصحيح وإعادة التشغيل هما سير العمل الأساسي
- تعتمد العديد من الأنظمة التابعة على أحداث النطاق
هذا لا يتعلق بالنضج المعماري. يتعلق الأمر بالتناسب.