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

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

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

ابدأ الدورة

مقدمة: لماذا SOLID مهم في TypeScript



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



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



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



النظرية

يجب أن يكون لكل class سبب واحد فقط للتغيير. هذا يعني أن الـ class يجب أن يكون مسؤولاً فقط عن جزء واحد من وظائف البرنامج. إذا كان الـ class يؤدي مهام متعددة، يصبح من الصعب صيانته واختباره.



النمط المضاد (انتهاك SRP)

class UserService {    saveUser(user: User): void {        // حفظ في قاعدة البيانات        console.log('User saved');    }

sendEmail(user: User, message: string): void { // إرسال البريد الإلكتروني console.log(`Email sent to ${user.email}`); }

generateReport(user: User): string { // إنشاء تقرير return `Report for ${user.name}`; }}


التطبيق الصحيح (SRP)

class UserRepository {    save(user: User): void {        // الحفظ فقط    }}

class EmailService { send(user: User, message: string): void { // إرسال البريد الإلكتروني فقط }}

class ReportGenerator { generate(user: User): string { // إنشاء التقارير فقط }}


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



النظرية

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



النمط المضاد (انتهاك OCP)

class PaymentProcessor {    processPayment(type: string, amount: number): void {        if (type === 'card') {            // معالجة البطاقة        } else if (type === 'paypal') {            // معالجة PayPal        } else if (type === 'crypto') {            // معالجة العملات الرقمية        }        // عند إضافة نوع جديد — يجب تغيير الـ class!    }}


التطبيق الصحيح (OCP)

interface PaymentMethod {    process(amount: number): void;}

class CardPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing card payment: $${amount}`); }}

class PayPalPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing PayPal payment: $${amount}`); }}

class PaymentProcessor { constructor(private paymentMethod: PaymentMethod) {}

process(amount: number): void { this.paymentMethod.process(amount); }}


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



النظرية

يجب أن تكون كائنات الـ class الأساسي قابلة للاستبدال بكائنات الـ subclasses الخاصة به دون تعطيل عمل البرنامج. يجب ألا تغير الـ subclasses السلوك المتوقع للـ class الأساسي.



النمط المضاد (انتهاك LSP)

class Rectangle {    constructor(public width: number, public height: number) {}

setWidth(width: number): void { this.width = width; }

setHeight(height: number): void { this.height = height; }

getArea(): number { return this.width * this.height; }}

class Square extends Rectangle {

المدونات

توصيات الكتب