البرمجة التفاعلية في C++: نهج حديث لمعالجة الأحداث
\n\nالبرمجة التفاعلية (Reactive Programming) هي نموذج يركز على تدفقات البيانات غير المتزامنة ونشر التغييرات. في C++، يسمح هذا المفهوم ببناء تطبيقات مرنة وسريعة الاستجابة وسهلة الصيانة، خاصة في مجالات واجهات المستخدم الرسومية (GUI) والتفاعل الشبكي ومعالجة الإشارات. على عكس النهج الأمري التقليدي، حيث تحدد بوضوح تسلسل الإجراءات، تصف البرمجة التفاعلية التبعيات بين البيانات: عندما يتغير عنصر واحد، يتم تحديث جميع العناصر المعتمدة عليه تلقائيًا.
\n\nالمفاهيم الأساسية للبرمجة التفاعلية
\n\n- \n
- Observable (قابل للملاحظة) — مصدر البيانات الذي يولد الأحداث. \n
- Observer (مراقب) — مشترك يستجيب للأحداث. \n
- Subscription (اشتراك) — العلاقة بين Observable وObserver. \n
- المشغلات (Operators) — دوال لتحويل وتصفية ودمج التدفقات (map, filter, merge, switch_on_next). \n
في C++، يتم تنفيذ البرمجة التفاعلية من خلال مكتبات توفر هذه التجريدات. دعنا نلقي نظرة على ثلاث أدوات شائعة.
\n\n1. RxCpp — مكتبة Reactive Extensions للغة C++
\n\nRxCpp هي نسخة من نموذج ReactiveX (Rx) الشهير للغة C++. توفر مجموعة قوية من المشغلات للعمل مع التدفقات غير المتزامنة. تستخدم المكتبة معايير C++17/20 الحديثة والقوالب (templates) وتعبيرات لامدا (lambda expressions).
\n\nمثال: اشتراك بسيط في تدفق أرقام
\n\n#include <rxcpp/rx.hpp>\n#include <iostream>\n\nint main() {\n // إنشاء تدفق أرقام قابل للملاحظة\n auto observable = rxcpp::observable<>::range(1, 5);\n\n // الاشتراك\n observable.subscribe(\n [](int v) { std::cout << "تم الاستلام: " << v << std::endl; }, // on_next\n []() { std::cout << "اكتمل!" << std::endl; } // on_completed\n );\n\n return 0;\n}\n\n\nمثال: التصفية والتحويل
\n\n#include <rxcpp/rx.hpp>\n#include <iostream>\n\nint main() {\n auto values = rxcpp::observable<>::range(1, 10)\n .filter([](int x) { return x % 2 == 0; }) // الأرقام الزوجية فقط\n .map([](int x) { return x * x; }); // التربيع\n\n values.subscribe([](int v) { std::cout << v << " "; });\n // الإخراج: 4 16 36 64 100\n\n return 0;\n}\n\n\nميزات RxCpp:
\n- \n
- دعم تعدد المهام (multithreading) والجدولة (schedulers). \n
- مجموعة غنية من المشغلات (merge, zip, combine_latest, debounce, throttle). \n
- التكامل مع std::future والعمليات غير المتزامنة. \n
- التوافق مع CMake وvcpkg. \n
2. Boost.Signals2 — الإشارات والفتحات بدون تبعيات خارجية
\n\nBoost.Signals2 هي مكتبة من مجموعة Boost، تطبق آلية الإشارات والفتحات. وهي تطور آمن للخيوط (thread-safe) من مكتبة Boost.Signals الأصلية. مثالية للهندسة المعمارية القائمة على الأحداث، خاصة في واجهات المستخدم الرسومية (GUI) ومحركات الألعاب.
\n\nمثال: إشارة بسيطة مع فتحتين
\n\n#include <boost/signals2.hpp>\n#include <iostream>\n\nvoid hello() { std::cout << "مرحبًا، "; }\nvoid world() { std::cout << "العالم!" << std::endl; }\n\nint main() {\n boost::signals2::signal<void()> sig;\n\n sig.connect(&hello);\n sig.connect(&world);\n\n sig(); // استدعاء الإشارة — سيستدعي كلتا الفتحتين\n // الإخراج: مرحبًا، العالم!\n\n return 0;\n}\n\n\nمثال: إشارة مع معلمات وقيمة إرجاع
\n\n#include <boost/signals2.hpp>\n#include <iostream>\n#include <string>