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

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

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

ابدأ الدورة

مبادئ SOLID في Java: من النظرية إلى التطبيق

\n\n

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

\n\n

لماذا نحتاج مبادئ SOLID؟

\n

بدون SOLID، يتحول الكود بسرعة إلى "سباغيتي". هل واجهت موقفًا يؤدي فيه تغيير كلاس واحد إلى كسر ثلاثة كلاسات أخرى؟ أو عندما تقوم دالة بعمل الكثير؟ SOLID يحل هذه المشكلات. كل مبدأ هو قاعدة تجعل الكود:

\n
    \n
  • مقاومًا للتغييرات — المتطلبات الجديدة لا تكسر المنطق القديم.
  • \n
  • واضحًا — كل كلاس مسؤول عن شيء واحد.
  • \n
  • قابلاً للاختبار — سهولة كتابة اختبارات الوحدة.
  • \n
\n\n

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

\n

الصياغة: "يجب أن يكون للكلاس سبب واحد فقط للتغيير".

\n

بكلمات بسيطة: يجب أن يقوم الكلاس بشيء واحد فقط. إذا كان للكلاس أكثر من مسؤولية، يصبح من الصعب صيانته.

\n\n

انتهاك SRP (كود سيء)

\n
public class OrderService {\n    public void createOrder(Order order) {\n        // منطق إنشاء الطلب\n        saveToDatabase(order);\n        sendEmailConfirmation(order);\n    }\n\n    private void saveToDatabase(Order order) {\n        // الحفظ في قاعدة البيانات\n    }\n\n    private void sendEmailConfirmation(Order order) {\n        // إرسال البريد الإلكتروني\n    }\n}
\n

المشكلة: الكلاس مسؤول عن منطق الأعمال، والعمل مع قاعدة البيانات، وإرسال الإشعارات. تغيير خدمة البريد الإلكتروني سيتطلب تغيير OrderService.

\n\n

التطبيق الصحيح لـ SRP

\n
public class OrderService {\n    private final OrderRepository repository;\n    private final EmailService emailService;\n\n    public OrderService(OrderRepository repo, EmailService email) {\n        this.repository = repo;\n        this.emailService = email;\n    }\n\n    public void createOrder(Order order) {\n        repository.save(order);\n        emailService.sendConfirmation(order);\n    }\n}\n\npublic class OrderRepository {\n    public void save(Order order) { /* منطق قاعدة البيانات */ }\n}\n\npublic class EmailService {\n    public void sendConfirmation(Order order) { /* منطق البريد الإلكتروني */ }\n}
\n

الآن كل كلاس له سبب واحد للتغيير. OrderService يتغير فقط عند تغيير عملية إنشاء الطلب.

\n\n

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

\n

الصياغة: "يجب أن تكون الكلاسات مفتوحة للتمديد، ولكن مغلقة للتعديل".

\n

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

\n\n

انتهاك OCP (كود سيء)

\n
public class AreaCalculator {\n    public double calculateArea(Object shape) {\n        if (shape instanceof Rectangle) {\n            Rectangle r = (Rectangle) shape;\n            return r.width * r.height;\n        } else if (shape instanceof Circle) {\n            Circle c = (Circle) shape;\n            return Math.PI * c.radius * c.radius;\n        }\n        throw new IllegalArgumentException("شكل غير معروف");\n    }\n}
\n

لإضافة مثلث، يجب تعديل الدالة calculateArea — وهذا ينتهك OCP.

\n\n

التطبيق الصحيح لـ OCP

\n
public interface Shape {\n    double calculateArea();\n}\n\npublic class Rectangle implements Shape {\n    private double width, height;\n    public Rectangle(double w, double h) { this.width = w; this.height = h; }\n    @Override\n    public double calculateArea() { return width * height; }\n}\n\npublic class Circle implements Shape {\n    private double radius;\n                

المدونات

توصيات الكتب