مبادئ SOLID في لغة C++: النظرية والتطبيق مع أمثلة برمجية

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

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

ابدأ الدورة

مبادئ SOLID في لغة C++: من النظرية إلى التطبيق



مبادئ SOLID هي خمس قواعد أساسية للتصميم الشيئي، صاغها روبرت مارتن. تساعد هذه المبادئ في إنشاء كود مرن وقابل للتوسع وسهل الصيانة. في هذه المقالة، سنشرح كل مبدأ مع أمثلة بلغة C++، من النظرية البسيطة إلى حالات عملية حقيقية.



1. مبدأ المسؤولية الواحدة (Single Responsibility Principle - SRP)



النظرية: يجب أن يكون لكل فئة سبب واحد فقط للتغيير. بمعنى آخر، الفئة مسؤولة فقط عن جزء واحد من وظائف البرنامج.



المشكلة: غالبًا ما يضع المطورون في فئة واحدة منطق التعامل مع البيانات وحفظها وعرضها على الشاشة. هذا ينتهك مبدأ SRP.



التطبيق في C++: سنقسم الفئة Report إلى ثلاث فئات منفصلة.



// سيء: ينتهك مبدأ SRPclass Report {    std::string title;    std::string content;public:    void generate() { /* توليد التقرير */ }    void saveToFile(const std::string& filename) { /* الحفظ في ملف */ }    void print() { /* الطباعة */ }};

// جيد: يلتزم بمبدأ SRPclass Report { std::string title; std::string content;public: void generate() { /* التوليد فقط */ }};

class ReportSaver {public: void saveToFile(const Report& report, const std::string& filename) { /* الحفظ */ }};

class ReportPrinter {public: void print(const Report& report) { /* الطباعة */ }};


الخلاصة: كل فئة الآن مسؤولة عن مهمتها الخاصة. أصبح الكود أسهل في الاختبار والتعديل.



2. مبدأ الفتح/الإغلاق (Open-Closed Principle - OCP)



النظرية: يجب أن تكون الكيانات البرمجية (الفئات، الوحدات، الدوال) مفتوحة للتمديد ولكن مغلقة للتعديل. أي يجب أن نكون قادرين على إضافة وظائف جديدة دون تغيير الكود الموجود.



التطبيق في C++: نستخدم تعدد الأشكال (Polymorphism) والفئات المجردة (Abstract Classes).



#include <iostream>#include <vector>#include <memory>

// الفئة الأساسية للأشكالclass Shape {public: virtual double area() const = 0; virtual ~Shape() = default;};

class Rectangle : public Shape { double width, height;public: Rectangle(double w, double h) : width(w), height(h) {} double area() const override { return width * height; }};

class Circle : public Shape { double radius;public: Circle(double r) : radius(r) {} double area() const override { return 3.14159 * radius * radius; }};

// فئة حساب المساحة الكلية - لا تتطلب تغييرات عند إضافة أشكال جديدةclass AreaCalculator {public: double totalArea(const std::vector<std::unique_ptr<Shape>>& shapes) { double total = 0; for (const auto& shape : shapes) { total += shape->area(); } return total; }};

int main() { std::vector<std::unique_ptr<Shape>> shapes; shapes.push_back(std::make_unique<Rectangle>(4, 5)); shapes.push_back(std::make_unique<Circle>(3));

AreaCalculator calc; std::cout << "Total area: " << calc.totalArea(shapes) << std::endl; return 0;}


الخلاصة: يمكننا إضافة أشكال جديدة (مثل Triangle) دون تعديل AreaCalculator.



3. مبدأ استبدال ليسكوف (Liskov Substitution Principle - LSP)



النظرية: يجب أن تكون الكائنات في البرنامج قابلة للاستبدال بنماذج من أنواعها الفرعية دون الإخلال بصحة البرنامج. ببساطة، إذا كان لديك فئة أب وفئة تابعة، فيجب أن تكون قادرًا على استخدام التابع حيثما يُتوقع الأب، ويجب أن يعمل كل شيء بشكل صحيح.



التطبيق

المدونات

توصيات الكتب