مبادئ SOLID في JavaScript: النظرية والتطبيق من الألف إلى الياء

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

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

ابدأ الدورة

مبادئ SOLID في JavaScript: النظرية والتطبيق من الألف إلى الياء

\n\n

تطوير برمجيات عالية الجودة لا يتطلب فقط معرفة بتركيب اللغة، بل أيضاً فهم مبادئ الهندسة المعمارية. SOLID هي خمسة مبادئ أساسية للتصميم كائني التوجه تساعد في إنشاء كود مرن وقابل للصيانة والتوسع. في هذه المقالة، سنشرح كل مبدأ من مبادئ SOLID في سياق JavaScript (Node.js) مع أمثلة عملية.

\n\n

ما هو SOLID؟

\n\n

تم تقديم اختصار SOLID بواسطة روبرت مارتن (العم بوب) ويتضمن المبادئ التالية:

\n\n
    \n
  • S — مبدأ المسؤولية الواحدة (Single Responsibility Principle)
  • \n
  • O — مبدأ الفتح/الإغلاق (Open/Closed Principle)
  • \n
  • L — مبدأ استبدال ليسكوف (Liskov Substitution Principle)
  • \n
  • I — مبدأ فصل الواجهات (Interface Segregation Principle)
  • \n
  • D — مبدأ عكس التبعيات (Dependency Inversion Principle)
  • \n
\n\n

هذه المبادئ عالمية وقابلة للتطبيق على أي لغة برمجة، بما في ذلك JavaScript. دعنا ننظر إلى كل منها بالتفصيل.

\n\n

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

\n\n

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

\n\n

مثال سيء: فئة UserService المسؤولة عن حفظ المستخدم، وإرسال البريد الإلكتروني، وإنشاء التقارير.

\n\n
// ❌ انتهاك SRP\nclass UserService {\n    saveUser(user) {\n        // حفظ في قاعدة البيانات\n        console.log('User saved');\n    }\n\n    sendEmail(user) {\n        // إرسال البريد الإلكتروني\n        console.log('Email sent to ' + user.email);\n    }\n\n    generateReport(user) {\n        // إنشاء تقرير\n        console.log('Report generated for ' + user.name);\n    }\n}
\n\n

مثال جيد: نقوم بتقسيم المسؤوليات إلى فئات منفصلة.

\n\n
// ✅ الامتثال لـ SRP\nclass UserRepository {\n    save(user) {\n        console.log('User saved');\n    }\n}\n\nclass EmailService {\n    send(user) {\n        console.log('Email sent to ' + user.email);\n    }\n}\n\nclass ReportGenerator {\n    generate(user) {\n        console.log('Report generated for ' + user.name);\n    }\n}\n\n// الاستخدام\nconst user = { name: 'إيفان', email: 'ivan@example.com' };\nconst userRepo = new UserRepository();\nconst emailService = new EmailService();\nconst reportGen = new ReportGenerator();\n\nuserRepo.save(user);\nemailService.send(user);\nreportGen.generate(user);
\n\n

الآن كل فئة لها مسؤولية واحدة، والتغييرات في وحدة واحدة لا تؤثر على الوحدات الأخرى.

\n\n

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

\n\n

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

\n\n

مثال سيء: دالة تحسب مساحة الأشكال باستخدام عبارات شرطية.

\n\n
// ❌ انتهاك OCP\nfunction calculateArea(shape) {\n    if (shape.type === 'circle') {\n        return Math.PI * shape.radius ** 2;\n    } else if (shape.type === 'rectangle') {\n        return shape.width * shape.height;\n    }\n    // عند إضافة شكل جديد، يجب تعديل الدالة\n    return 0;\n}
\n\n

مثال جيد: نستخدم تعدد الأشكال والوراثة.

\n\n
// ✅ الامتثال لـ OCP\nclass Shape {\n    area() {\n        throw new Error('يجب تنفيذ طريقة area()');\n    }\n}\n\nclass Circle extends Shape {\n    constructor(radius) {\n        super();\n        this.radius = radius;\n    }\n\n    area() {\n        return Math.PI * this.radius ** 2;\n    }\n}\n\nclass Rectangle extends Shape {\n    constructor                

المدونات

توصيات الكتب