مبادئ SOLID في TypeScript: المستوى المتقدم مع أمثلة

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

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

ابدأ الدورة

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

\n\n

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

\n\n

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

\n\n

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

\n\n

التطبيق المتقدم: غالباً ما يظهر انتهاك SRP في "الكائنات الإلهية" (God Objects). استخدم التركيب والتفويض.

\n\n
// ❌ انتهاك SRP: الفئة مسؤولة عن البيانات والتحقق والحفظ\nclass UserService {\n  constructor(private user: User) {}\n\n  validateEmail(email: string): boolean {\n    return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n  }\n\n  saveToDatabase(): void {\n    // منطق الحفظ\n  }\n\n  sendWelcomeEmail(): void {\n    // منطق الإرسال\n  }\n}\n\n// ✅ SRP: فصل المسؤوليات\ninterface IEmailValidator {\n  isValid(email: string): boolean;\n}\n\ninterface IUserRepository {\n  save(user: User): Promise<void>;\n}\n\ninterface INotificationService {\n  sendWelcome(user: User): Promise<void>;\n}\n\nclass UserRegistrationService {\n  constructor(\n    private validator: IEmailValidator,\n    private repository: IUserRepository,\n    private notifier: INotificationService\n  ) {}\n\n  async register(user: User): Promise<void> {\n    if (!this.validator.isValid(user.email)) {\n      throw new Error('بريد إلكتروني غير صالح');\n    }\n    await this.repository.save(user);\n    await this.notifier.sendWelcome(user);\n  }\n}
\n\n

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

\n\n

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

\n\n

التطبيق المتقدم: استخدم نمط "الاستراتيجية" (Strategy) لتطبيق OCP.

\n\n
// ❌ انتهاك OCP: عند إضافة نوع تقرير جديد، يجب تعديل الفئة\nclass ReportGenerator {\n  generate(data: any[], type: string): string {\n    if (type === 'csv') {\n      return data.map(row => row.join(',')).join('\\n');\n    } else if (type === 'json') {\n      return JSON.stringify(data);\n    }\n    // عند إضافة 'xml' — نقوم بتعديل هذه الطريقة\n    throw new Error('تنسيق غير مدعوم');\n  }\n}\n\n// ✅ OCP: استخدام تعدد الأشكال\ninterface IReportFormatter {\n  format(data: any[]): string;\n}\n\nclass CsvFormatter implements IReportFormatter {\n  format(data: any[]): string {\n    return data.map(row => row.join(',')).join('\\n');\n  }\n}\n\nclass JsonFormatter implements IReportFormatter {\n  format(data: any[]): string {\n    return JSON.stringify(data);\n  }\n}\n\nclass XmlFormatter implements IReportFormatter {\n  format(data: any[]): string {\n    // تنفيذ XML\n    return '<data>...</data>';\n  }\n}\n\nclass ReportGeneratorOCP {\n  constructor(private formatter: IReportFormatter) {}\n\n  generate(data: any[]): string {\n    return this.formatter.format(data);\n  }\n}\n\n// الاستخدام: التوسع دون تعديل\nconst csvReport = new ReportGeneratorOCP(new CsvFormatter());\nconst jsonReport = new ReportGeneratorOCP(new JsonFormatter());
\n\n

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

\n\n

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

المدونات

توصيات الكتب