هندسة Event-driven بلغة Kotlin: لماذا ليست مجرد موضة عابرة
\nتخيل أن تطبيقك عبارة عن آلية مضبوطة بإتقان. كل ترس يعرف متى يدور، وكل مكبس يعرف متى يتحرك. ولكن ماذا لو احتجت يومًا ما إلى إضافة جزء جديد دون إيقاف الآلة بأكملها؟ في الهندسة التقليدية المتزامنة، غالبًا ما يتحول هذا إلى كابوس: إعادة كتابة وحدات كاملة، اختبار سلاسل لا نهائية من الاستدعاءات، وليالٍ بلا نوم.
\nهنا تظهر هندسة Event-driven بلغة Kotlin - نموذج حيث تتواصل المكونات عبر الأحداث، وليس عبر الاستدعاءات المباشرة. Kotlin، مع كوروتيناتها وتدفقاتها التفاعلية، يوفر أدوات مثالية لذلك. في هذه المقالة، لن نتحدث عن النظرية فقط - بل سنكتب كودًا حقيقيًا، ونحلل Kotlin Flow و Channels، وسأريكم كيفية بناء نظام مرن وقابل للتوسع لا ينهار عند أول حمل.
\n\nما هي الهندسة الموجهة بالأحداث بلغة بسيطة
\nفي النهج التقليدي (تخيل خدمات مصغرة تتصل ببعضها عبر REST)، كل طلب هو ارتباط صارم. الخدمة (أ) تستدعي الخدمة (ب)، وتنتظر الرد، وإذا تعطلت (ب) - ينهار كل شيء. في هندسة Event-driven، الأمر مختلف تمامًا: المكونات تنشر الأحداث (مثل "تم إنشاء الطلب") وتشترك فيها. لا أحد ينتظر أحدًا، ولا أحد يتصل بأي شخص مباشرة.
\nروعة Kotlin تكمن في أنه يسمح بتنفيذ هذا النموذج بشكل أصلي، دون الحاجة إلى أطر عمل ضخمة. الكوروتينات توفر خيوطًا خفيفة الوزن، و Channel و Flow يوفران نواقل جاهزة للأحداث.
\nلنلقِ نظرة على مثال بسيط - EventBus خاص بنا بلغة Kotlin:
\n\nimport kotlinx.coroutines.*\nimport kotlinx.coroutines.channels.*\n\nclass SimpleEventBus {\n private val events = Channel<Any>(Channel.UNLIMITED)\n\n suspend fun publish(event: Any) {\n events.send(event)\n }\n\n suspend fun subscribe(handler: suspend (Any) -> Unit) {\n for (event in events) {\n handler(event)\n }\n }\n}\n\n// الاستخدام\nfun main() = runBlocking {\n val bus = SimpleEventBus()\n \n launch {\n bus.subscribe { event ->\n println("تم استلام الحدث: $event")\n }\n }\n \n delay(100)\n bus.publish("Hello, Event-Driven!")\n delay(100)\n}\n\nهذا الكود هو الأساس. نقوم بإنشاء قناة تعمل كطابور غير متزامن. الناشر يضع الحدث، والمشترك يسحبه. كل شيء بسيط، ولكن هنا تظهر قوة هندسة Event-driven بلغة Kotlin: المشترك والناشر لا يعرفان شيئًا عن بعضهما البعض.
\n\nKotlin Flow: تدفقات تفاعلية للأحداث
\nChannel رائع، ولكن للمشاريع الحقيقية غالبًا ما نحتاج إلى المزيد: تدفقات باردة وساخنة، تحويلات، معالجة الأخطاء. هنا يأتي دور Kotlin Flow - مكتبة تفاعلية مدمجة مباشرة في اللغة.
\nFlow مثالي لـ البرمجة غير المتزامنة بلغة Kotlin، عندما يتم توليد الأحداث باستمرار. على سبيل المثال، تحديثات أسعار العملات، خلاصات الأخبار، أو حالة واجهة المستخدم.
\n\nالتدفقات الباردة مقابل التدفقات الساخنة
\nمن المهم فهم الفرق:
\n- \n
- التدفق البارد (Cold Stream) - يبدأ العمل فقط عند الاشتراك فيه. كل مشترك يحصل على دفق البيانات الخاص به. \n
- التدفق الساخن (Hot Stream) - يعمل باستمرار، بغض النظر عن المشتركين. المشتركون المتأخرون يفوتون الأحداث القديمة. \n
لهندسة Event-driven، عادةً ما نحتاج إلى تدفقات ساخنة. في Kotlin، يتم تنفيذها عبر SharedFlow أو StateFlow.
مثال - نظام الإشعارات:
\n\nimport kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\ndata class Notification(val userId: String, val message: String)\n\nclass NotificationService {\n private val _notifications = MutableSharedF