مقدمة: لماذا SOLID مهم لمطور Java
في عالم البرمجة كائنية التوجه، تصبح صيانة الكود وتوسيعه أكثر تعقيدًا بمرور الوقت. بدون بنية واضحة، حتى المشروع الصغير يتحول إلى "كتلة طين كبيرة"، حيث يؤدي تغيير وظيفة واحدة إلى كسر عشر وظائف أخرى. هنا تأتي مبادئ SOLID للإنقاذ — خمس قواعد أساسية لتصميم الفئات، صاغها روبرت مارتن (العم بوب).
بالنسبة لمطور Java، فإن SOLID ليست مجرد نظرية، بل أداة عملية. Java، كلغة ذات كتابة صارمة ونظام قوي من الواجهات والوراثة، مثالية لتنفيذ هذه المبادئ. في هذه المقالة، سنشرح كل مبدأ من الناحية النظرية ونعرض أمثلة حية على كود Java يمكن تطبيقها فورًا في المشروع.
1. Single Responsibility Principle (مبدأ المسؤولية الفردية)
النظرية
SRP ينص على: يجب أن يكون للفئة سبب واحد فقط للتغيير. بمعنى آخر، يجب أن تكون الفئة مسؤولة عن وظيفة واحدة محددة بوضوح. إذا كانت الفئة تفعل الكثير، يصبح اختبارها وتعديلها وإعادة استخدامها أمرًا صعبًا.
التطبيق العملي في Java
لننظر إلى انتهاك نموذجي لـ SRP — فئة تدير بيانات المستخدم وترسل الإشعارات في نفس الوقت:
// ❌ انتهاك SRPpublic class User { private String name; private String email;
public void saveToDatabase() { // حفظ في قاعدة البيانات }
public void sendWelcomeEmail() { // إرسال بريد إلكتروني }}الحل الصحيح هو تقسيم المسؤولية إلى فئتين:
// ✅ الامتثال لـ SRPpublic class User { private String name; private String email; // Getters and Setters}
public class UserRepository { public void save(User user) { // حفظ في قاعدة البيانات }}
public class EmailService { public void sendWelcomeEmail(User user) { // إرسال بريد إلكتروني }}الخلاصة: كل فئة الآن لديها سبب واحد للتغيير. User يتغير فقط عند تغيير بنية البيانات، UserRepository — عند تغيير منطق قاعدة البيانات، EmailService — عند تغيير قوالب البريد الإلكتروني.
2. Open-Closed Principle (مبدأ الانفتاح/الإغلاق)
النظرية
OCP يؤكد: يجب أن تكون الفئات مفتوحة للتمديد، ولكن مغلقة للتعديل. هذا يعني أنه يجب إضافة الوظائف الجديدة من خلال الوراثة أو التركيب، دون لمس الكود الذي تم اختباره بالفعل.
التطبيق العملي في Java
تخيل أن لديك آلة حاسبة للخصم لأنواع مختلفة من العملاء:
// ❌ انتهاك OCPpublic class DiscountCalculator { public double calculateDiscount(String customerType, double amount) { if (customerType.equals("Regular")) { return amount * 0.1; } else if (customerType.equals("Premium")) { return amount * 0.2; } return 0; }}عند إضافة نوع جديد من العملاء (مثل "Gold")، سيتعين عليك تعديل الفئة الحالية. الحل هو استخدام تعدد الأشكال:
// ✅ الامتثال لـ OCPpublic interface DiscountStrategy { double calculate(double amount);}
public class RegularDiscount implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.1; }}
public class PremiumDiscount implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.2; }}
public class DiscountCalculator { private DiscountStrategy strategy;
public DiscountCalculator(DiscountStrategy strategy) { this.strategy = strategy; }
public double calculate(double amount) {```