أنماط العمارة في C++: كيف تكتب كودًا لا تخجل من عرضه

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا C++ بدون عمارة هو ألم

\n

إذا سبق لك أن فتحت مشروع C++ لشخص آخر (أو مشروعك القديم) وشعرت بأن عينيك تدمعان من آلاف الأسطر في ملف واحد، وأصبحت عملية التجميع طقسًا يتطلب فنجان قهوة - فأنت لست وحدك. C++ يمنح حرية هائلة: يمكنك مزج الأنماط، تحميل العوامل، والقيام بسحر القوالب. لكن الحرية بدون انضباط تؤدي إلى الفوضى.

\n

أنماط العمارة في C++ ليست نظرية مملة من محاضرات الجامعة. إنها وصفات قتالية مجربة تنقذ المشروع عندما ينمو من "لعبة" إلى مشروع صناعي. في هذه المقالة سنستعرض أنماط العمارة في C++ التي تبسط الحياة حقًا: من MVC إلى Observer. ونعم، سيكون هناك الكثير من الكود.

\n\n

ما هو النمط المعماري (وكيف يختلف عن "مجرد نمط")

\n

كثيرون يخلطون بين أنماط التصميم في C++ (GoF: Singleton, Factory, Adapter) والأنماط المعمارية. الفرق بسيط:

\n
    \n
  • أنماط التصميم - حلول دقيقة على مستوى الفئة أو الوحدة (مثل كيفية إنشاء كائن).
  • \n
  • أنماط العمارة - حلول كلية على مستوى التطبيق بأكمله (كيف تتواصل المكونات، كيف يتم فصل الطبقات).
  • \n
\n

العمارة تحدد ما إذا كان مشروعك سيتحول إلى "كرة طين كبيرة" (Big Ball of Mud) بعد ستة أشهر. لذلك دعونا نلقي نظرة على ثلاثة من أكثر الأنماط فائدة لـ C++.

\n\n

1. MVC (Model-View-Controller) في C++: فرق تسد

\n

MVC هو كلاسيكي. يقسم التطبيق إلى ثلاثة أجزاء: البيانات (Model)، العرض (View)، ومنطق التحكم (Controller). في C++، هذا مهم بشكل خاص لتطبيقات الواجهات الرسومية (Qt, wxWidgets) أو حتى الأدوات الطرفية.

\n\n

كيف يبدو ذلك في الكود

\n

لنتخيل آلة حاسبة بسيطة. النموذج يخزن النتيجة، العرض يعرضها، والمتحكم يعالج الإدخال.

\n
#include <iostream>\n#include <string>\n\n// Model: لا يعرف شيئًا عن الواجهة الرسومية\nclass CalculatorModel {\npublic:\n    double add(double a, double b) {\n        result_ = a + b;\n        return result_;\n    }\n    double getResult() const { return result_; }\nprivate:\n    double result_ = 0;\n};\n\n// View: فقط العرض\nclass CalculatorView {\npublic:\n    void showResult(double value) {\n        std::cout << "النتيجة: " << value << std::endl;\n    }\n    void showError(const std::string& msg) {\n        std::cerr << "خطأ: " << msg << std::endl;\n    }\n};\n\n// Controller: يربط Model و View\nclass CalculatorController {\npublic:\n    CalculatorController(CalculatorModel& model, CalculatorView& view)\n        : model_(model), view_(view) {}\n\n    void handleAdd(double a, double b) {\n        double res = model_.add(a, b);\n        view_.showResult(res);\n    }\nprivate:\n    CalculatorModel& model_;\n    CalculatorView& view_;\n};\n\nint main() {\n    CalculatorModel model;\n    CalculatorView view;\n    CalculatorController controller(model, view);\n\n    controller.handleAdd(5, 3); // الإخراج: النتيجة: 8\n    return 0;\n}
\n

لماذا هذا رائع؟ يمكنك استبدال View الطرفية بأداة Qt دون لمس Model. أو إضافة اختبارات وحدة لـ Model دون تشغيل الواجهة الرسومية. هذا هو أساس تصميم تطبيقات C++ من الصفر.

\n\n

2. Observer (المراقب): عندما يجب أن تكون التغييرات ملحوظة للجميع

\n

تخيل: لديك مستشعر درجة حرارة، ويجب تحديث عدة لوحات عندما تتغير درجة الحرارة. بدلاً من استقصاء المستشعر كل ثانية (polling)، يقوم Observer بإخطار المشتركين بنفسه. هذا نمط معماري في C++ يجعل الكود موجهًا بالأحداث.

\n\n

التنفيذ باستخدام C++11 وما بعده

\n

نستخدم المؤشرات الذكية و std::function للمرونة.

\n
#include <iostream>\n#include <vector>\n#include <memory>\n#include <functional>\n\n// واجهة المراقب\nclass IObserv                

المدونات

توصيات الكتب