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

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

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

ابدأ الدورة

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



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



1. S — مبدأ المسؤولية الفردية (Single Responsibility Principle)



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



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



class User {    constructor(name, email) {        this.name = name;        this.email = email;    }

saveToDatabase() { // منطق الحفظ في قاعدة البيانات console.log(`حفظ المستخدم ${this.name} في قاعدة البيانات`); }

sendWelcomeEmail() { // منطق إرسال البريد الإلكتروني console.log(`إرسال رسالة ترحيبية إلى ${this.email}`); }}


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



class User {    constructor(name, email) {        this.name = name;        this.email = email;    }}

class UserRepository { save(user) { console.log(`حفظ المستخدم ${user.name} في قاعدة البيانات`); }}

class EmailService { sendWelcome(user) { console.log(`إرسال رسالة ترحيبية إلى ${user.email}`); }}

// الاستخدامconst user = new User('إيفان', 'ivan@example.com');const repo = new UserRepository();const emailService = new EmailService();

repo.save(user);emailService.sendWelcome(user);


2. O — مبدأ مفتوح-مغلق (Open-Closed Principle)



يجب أن تكون الكيانات البرمجية مفتوحة للتمديد ولكن مغلقة للتعديل. هذا يعني أنه يجب إضافة الوظائف الجديدة من خلال كود جديد، وليس عن طريق تغيير الكود الموجود.



مثال سيء: فئة AreaCalculator تتطلب تعديلًا عند إضافة شكل جديد.



class AreaCalculator {    calculate(shape) {        if (shape.type === 'circle') {            return Math.PI * shape.radius ** 2;        } else if (shape.type === 'rectangle') {            return shape.width * shape.height;        }        // عند إضافة شكل جديد، يجب تغيير هذه الطريقة    }}


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



class Shape {    area() {        throw new Error('يجب إعادة تعريف الطريقة area()');    }}

class Circle extends Shape { constructor(radius) { super(); this.radius = radius; }

area() { return Math.PI * this.radius ** 2; }}

class Rectangle extends Shape { constructor(width, height) { super(); this.width = width; this.height = height; }

area() { return this.width * this.height; }}

class AreaCalculator { calculate(shape) { return shape.area(); }}

// الاستخدامconst calculator = new AreaCalculator();const circle = new Circle(5);const rectangle = new Rectangle(4, 6);

console.log(calculator.calculate(circle)); // 78.54console.log(calculator.calculate(rectangle)); // 24


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



يجب أن تكون الكائنات في البرنامج قابلة للاستبدال بنسخ من فئاتها الفرعية دون التأثير على صحة البرنامج.

المدونات

توصيات الكتب