مقدمة: وجهان لعملة واحدة
\n\nتخيل أنك تبني منزلاً. يمكنك أخذ كتل جاهزة (كلاسات، كائنات، وراثة) وتجميعها في هيكل معقد - هذه هي البرمجة كائنية التوجه (OOP). أو يمكنك التفكير كعالم رياضيات: "آخذ البيانات، وأطبق عليها دالة نقية وأحصل على نتيجة جديدة، دون تغيير أي شيء" - هذه هي البرمجة الوظيفية.
\n\nفي C#، يتعايش كلا النموذجين بشكل مذهل. وإذا كنت تكتب بهذه اللغة، فستسأل نفسك عاجلاً أم آجلاً: "ماذا لو كنت أفعل هذا بشكل خاطئ؟ ربما يجب أن أستخدم LINQ أكثر وكلاسات أقل؟"
\n\nفي هذه المقالة، لن نتجادل حول أيهما أفضل. سنفهم كيف يختلف المنهج الوظيفي عن البرمجة كائنية التوجه في C#، ومتى يساعد كل منهما حقًا، ومتى يضر. ونعم، سيكون هناك الكثير من الكود. هيا بنا!
\n\n1. البرمجة كائنية التوجه في C#: الكلاسيكية التي تعمل
\n\nالبرمجة كائنية التوجه تتعلق بالحالة والسلوك. لديك كلاس يخزن البيانات (حقول، خصائص) ودوال تقوم بتعديل هذه البيانات.
مثال: تطبيق لإدارة الطلبات في متجر إلكتروني.
\n\npublic class Order\n{\n public int Id { get; set; }\n public List<string> Items { get; private set; }\n public decimal TotalPrice { get; private set; }\n\n public Order(int id)\n {\n Id = id;\n Items = new List<string>();\n TotalPrice = 0;\n }\n\n public void AddItem(string itemName, decimal price)\n {\n Items.Add(itemName);\n TotalPrice += price;\n }\n\n public void ApplyDiscount(decimal percent)\n {\n TotalPrice -= TotalPrice * (percent / 100);\n }\n}\n\nماذا نرى؟ التغليف: لا يمكن تغيير TotalPrice مباشرة - فقط من خلال الدوال. حالة الكائن تتغير بمرور الوقت: نضيف منتجات، نطبق خصومات. هذه برمجة كائنية التوجه خالصة.
مزايا البرمجة كائنية التوجه في C#
\n- \n
- نموذج مفهوم للعالم الحقيقي: طلب، عميل، منتج - كل شيء كما في الحياة. \n
- إعادة الاستخدام من خلال الوراثة والواجهات. \n
- إدارة التعقيد عن طريق التقسيم إلى كائنات صغيرة. \n
عيوب البرمجة كائنية التوجه
\n- \n
- الآثار الجانبية: يمكن لدالة واحدة تغيير الحالة، ويسهل فقدان السيطرة. \n
- صعوبة الاختبار: تحتاج لإنشاء كائنات ومحاكاة التبعيات. \n
- التكرار: أحيانًا يكون كتابة دالة أسهل من إنشاء كلاس كامل. \n
2. المنهج الوظيفي في C#: LINX وأكثر
\n\nالبرمجة الوظيفية تتعلق بـ الدوال النقية (بدون آثار جانبية) و ثبات البيانات. في C#، يظهر هذا بشكل خاص في LINQ، تعابير لامدا، والعمل مع المجموعات.
\n\nلنحل نفس المهمة - إدارة الطلب - ولكن بطريقة وظيفية.
\n\n// سجل غير قابل للتغيير (record)\npublic record Order(int Id, List<string> Items, decimal TotalPrice);\n\npublic static class OrderFunctions\n{\n public static Order AddItem(Order order, string item, decimal price)\n {\n var newItems = order.Items.Append(item).ToList();\n return order with { Items = newItems, TotalPrice = order.TotalPrice + price };\n }\n\n public static Order ApplyDiscount(Order order, decimal percent)\n {\n return order with { TotalPrice = order.TotalPrice * (1 - percent / 100) };\n }\n}\n\n// الاستخدام\nvar order = new Order(1, new List<string>(), 0);\norder = OrderFunctions.AddItem(order, "لابتوب", 50000);\norder = OrderFunctions.ApplyDiscount(order, 10);\n\nهل لاحظت؟ نحن لا نغير الكائن الأصلي. في كل مرة يتم إنشاء نسخة جديدة باستخدام with. هذا يمنع التغييرات العشوائية.
أ