في عالم تطوير البرمجيات سريع الإيقاع، كتابة كود يعمل هي نصف المعركة فقط. النصف الآخر هو كتابة كود سهل الصيانة والتوسيع والتطوير. وهنا تأتي مبادئ SOLID. صاغها روبرت سي. مارتن، وتعمل هذه المبادئ الخمسة لتصميم كود كائني التوجه يظل قويًا حتى مع تغيّر المتطلبات. للمطورين من المستوى المتوسط إلى المتقدم، لا يقتصر إتقان SOLID على اتباع القواعد فحسب؛ بل يتعلق بتبني عقلية تعطي الأولوية للمرونة والوضوح.
1. مبدأ المسؤولية الواحدة (SRP)
يجب أن يكون للفئة سبب واحد فقط للتغيير. إذا كانت الفئة تتعامل مع منطق الأعمال وتخزين البيانات معًا، فإنها تنتهك مبدأ SRP. فصل الاهتمامات يضمن أن التغييرات في جانب واحد من النظام لا تكسر جانبًا آخر عن غير قصد.
// سيء: فئة واحدة تؤدي مهام متعددة
public class User {
public void save() { /* منطق قاعدة البيانات */ }
public void sendEmail() { /* منطق البريد الإلكتروني */ }
}
// جيد: فصل المسؤوليات
public class UserRepository {
public void save(User user) { /* منطق قاعدة البيانات */ }
}
public class EmailService {
public void sendWelcome(User user) { /* منطق البريد الإلكتروني */ }
}
2. مبدأ المفتوح/المغلق (OCP)
يجب أن تكون كيانات البرمجيات مفتوحة للتوسيع ومغلقة للتعديل. بدلاً من تغيير الكود الموجود لإضافة ميزات جديدة، يجب عليك توسيعه. غالبًا ما يتم تحقيق ذلك من خلال التجريد والسيما (Polymorphism).
// سيء: تعديل الكود الموجود
public class Discount {
public double calculate(Invoice invoice) {
if (invoice.getType() == "VIP") return invoice.getTotal() * 0.9;
// يصعب إضافة أنواع جديدة دون مخاطر
}
}
// جيد: التوسيع عبر نمط الاستراتيجية
public interface DiscountStrategy {
double calculate(Invoice invoice);
}
public class VipDiscount implements DiscountStrategy {
public double calculate(Invoice invoice) {
return invoice.getTotal() * 0.9;
}
}
3. مبدأ استبدال ليسكوف (LSP)
يجب أن تكون كائنات الفئة الأصلية قابلة للاستبدال بكائنات الفئة الفرعية دون كسر التطبيق. يضمن هذا الاستخدام الصحيح للإرث وأن الأنواع الفرعية هي في الحقيقة سلوكيات لأنواعها الأصلية.
على سبيل المثال، لا ينبغي أن ترث فئة Square (مربع) من فئة Rectangle (مستطيل) لأن تعيين عرض المربع لا معنى له بنفس الطريقة كما هو الحال مع المستطيل، مما ينتهك التوقعات السلوكية.
4. مبدأ فصل الواجهات (ISP)
لا ينبغي إجبار العملاء على الاعتماد على واجهات لا يستخدمونها. من الأفضل وجود عدة واجهات محددة بدلاً من واجهة واحدة عامة. يقلل هذا من الاقتران ويجعل الكود أسهل في الفهم.
// سيء: واجهة كبيرة
public interface Worker {
void work();
void eat();
void sleep();
}
// جيد: واجهات مفصولة
public interface Workable {
void work();
}
public interface Eatable {
void eat();
}
5. مبدأ عكس الاعتمادية (DIP)
لا ينبغي أن تعتمد الوحدات عالية المستوى على الوحدات منخفضة المستوى. يجب أن تعتمد كلتاهما على التجريدات. يعزز هذا الاقتران الضعيف ويجعل الاختبار أسهل من خلال السماح بتقليد الاعتماديات أو استبدالها.
// سيء: اعتمادية مباشرة
public class OrderService {
private MySqlDatabase db = new MySqlDatabase();
}
// جيد: الاعتماد على التجريد
public class OrderService {
private Database db;
public OrderService(Database db) {
this.db = db;
}
}
الخلاصة
تطبيق مبادئ SOLID لا يعني أنك يجب أن تلتزم بها بشكل صارم في كل سطر من الكود. بدلاً من ذلك، استخدمها كإرشادات للكشف عن متى يصبح تصميمك هشًا. من خلال التركيز على المسؤولية الواحدة، والمفتوح/المغلق، واستبدال ليسكوف، وفصل الواجهات، وعكس الاعتمادية، يمكنك بناء برمجيات ليست وظيفية اليوم فحسب، بل قابلة للتكيف مع تحديات الغد أيضًا.