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

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

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

ابدأ الدورة

مقدمة في مبادئ SOLID في JavaScript

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

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



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

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

انتهاك SRP

لننظر إلى الفئة UserService التي تدير المستخدمين وترسل البريد الإلكتروني وتسجل الإجراءات في نفس الوقت:

class UserService {  constructor() {    this.users = [];  }

addUser(name) { this.users.push({ name }); console.log('User added'); // تسجيل this.sendEmail(name); // إرسال البريد الإلكتروني }

sendEmail(name) { console.log(`Email sent to ${name}`); }

getUsers() { return this.users; }}

هنا، الفئة لديها ثلاث مسؤوليات: إدارة البيانات، التسجيل، وإرسال الإشعارات. تغيير منطق التسجيل أو إرسال البريد الإلكتروني سيؤدي إلى تغيير الفئة UserService.

الالتزام بـ SRP

سنفصل المسؤوليات إلى فئات منفصلة:

class Logger {  log(message) {    console.log(`[LOG]: ${message}`);  }}

class EmailService { send(name) { console.log(`Email sent to ${name}`); }}

class UserService { constructor(logger, emailService) { this.users = []; this.logger = logger; this.emailService = emailService; }

addUser(name) { this.users.push({ name }); this.logger.log(`User ${name} added`); this.emailService.send(name); }

getUsers() { return this.users; }}

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



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

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

انتهاك OCP

لنفترض أن لدينا دالة لحساب مساحة الأشكال:

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

الالتزام بـ OCP

سنستخدم تعدد الأشكال من خلال الفئات:

class Shape {  area() {    throw new Error('Method "area()" must be implemented');  }}

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 Triangle extends Shape { constructor(base, height) { super(); this.base = base; this.height = height; } area() { return (this.base * this.height) / 2; }}

function calculateArea

المدونات

توصيات الكتب