مقدمة في مبادئ SOLID في لغة C#
\nالتطوير بلغة C# في بيئة .NET لا يتطلب فقط معرفة بناء الجملة، بل يتطلب أيضًا القدرة على تصميم أنظمة مرنة وقابلة للصيانة والاختبار. ولهذا الغرض تم إنشاء مبادئ SOLID — وهي خمس قواعد أساسية للبرمجة كائنية التوجه، صاغها روبرت مارتن (العم بوب).
\nاختصار SOLID يعني:
\n- \n
- S — Single Responsibility Principle (مبدأ المسؤولية الواحدة) \n
- O — Open/Closed Principle (مبدأ الانفتاح/الإغلاق) \n
- L — Liskov Substitution Principle (مبدأ استبدال ليسكوف) \n
- I — Interface Segregation Principle (مبدأ فصل الواجهات) \n
- D — Dependency Inversion Principle (مبدأ عكس التبعيات) \n
في هذه المقالة، سنشرح كل مبدأ عمليًا مع أمثلة بلغة C#، ونوضح كيف يؤدي انتهاكها إلى مشاكل، وكيف أن التطبيق الصحيح يجعل الكود أنظف.
\n\n1. مبدأ المسؤولية الواحدة (SRP)
\nالجوهر: يجب أن يكون للفصل سبب واحد فقط للتغيير. بمعنى آخر، كل فصل مسؤول عن مهمة واحدة محددة بوضوح.
\n\nانتهاك SRP في C#
\nلنأخذ مثالًا نموذجيًا — فصل OrderService الذي يفعل الكثير:
public class OrderService\n{\n public void ProcessOrder(Order order)\n {\n // 1. الحفظ في قاعدة البيانات\n SaveToDatabase(order);\n \n // 2. إرسال البريد الإلكتروني\n SendEmail(order.CustomerEmail, "تم تأكيد الطلب");\n \n // 3. التسجيل\n File.WriteAllText("log.txt", $"تم معالجة الطلب {order.Id}");\n }\n \n private void SaveToDatabase(Order order) { /* ... */ }\n private void SendEmail(string email, string message) { /* ... */ }\n}\nالمشكلة: تغيير منطق إرسال البريد الإلكتروني أو طريقة التسجيل سيؤدي إلى تغيير فصل OrderService. هذا ينتهك SRP.
التنفيذ الصحيح لـ SRP
\nنقوم بتقسيم المسؤولية إلى خدمات منفصلة:
\npublic class OrderProcessor\n{\n private readonly IOrderRepository _repository;\n private readonly INotificationService _notificationService;\n private readonly ILogger _logger;\n \n public OrderProcessor(\n IOrderRepository repository,\n INotificationService notificationService,\n ILogger logger)\n {\n _repository = repository;\n _notificationService = notificationService;\n _logger = logger;\n }\n \n public void ProcessOrder(Order order)\n {\n _repository.Save(order);\n _notificationService.SendConfirmation(order.CustomerEmail);\n _logger.Log($"تم معالجة الطلب {order.Id}");\n }\n}\n\npublic interface IOrderRepository { void Save(Order order); }\npublic interface INotificationService { void SendConfirmation(string email); }\npublic interface ILogger { void Log(string message); }\nالآن كل فصل مسؤول فقط عن مهمته. تغيير منطق التسجيل لا يؤثر على معالجة الطلبات.
\n\n2. مبدأ الانفتاح/الإغلاق (OCP)
\nالجوهر: يجب أن تكون الفصول مفتوحة للتمديد ولكن مغلقة للتعديل. أي يجب أن تكون قادرًا على إضافة سلوك جديد دون تغيير الكود الموجود.
\n\nانتهاك OCP في C#
\nمثال كلاسيكي — آلة حاسبة مع شروط:
\npublic class AreaCalculator\n{\n public double CalculateArea(object shape)\n {\n if (shape is Rectangle rect)\n return rect.Width * rect.Height;\n else if (shape is Circle circle)\n return Math.PI * circle.Radius * circle.Radius;\n // إضافة شكل جديد يتطلب تغيير هذه الطريقة!\n throw new NotSupportedException();\n }\n}