وجهان لعملة واحدة: المنهج الوظيفي مقابل المنهج كائني التوجه في Swift
\n\nعندما بدأت البرمجة لنظام iOS، اعتقدت أن البرمجة كائنية التوجه هي الطريق الصحيح الوحيد. الفئات، الوراثة، تعدد الأشكال – كل هذا بدا وكأنه كتاب مقدس للمطور. لكن بعد ذلك اكتشفت البرمجة الوظيفية في Swift، وانقلب عالمي رأساً على عقب. اتضح أنه يمكنك كتابة كود لا يغير الحالة، يسهل اختباره، ويبدو كصيغة رياضية.
\n\nSwift لغة فريدة من نوعها. إنها متعددة النماذج. هذا يعني أنه يمكنك مزج البرمجة كائنية التوجه والمنهج الوظيفي في مشروع واحد، والاستفادة من أفضل ما في العالمين. لكن كيف لا ترتبك؟ متى تستخدم الفئات، ومتى تستخدم الإغلاقات و map؟ دعنا نفهم ذلك.
\n\nSwift كائني التوجه: الكلاسيكية التي تعمل
\n\nالبرمجة كائنية التوجه في Swift تُبنى حول الفئات والبروتوكولات والوراثة. هذا نموذج حيث تعيش البيانات والسلوك معاً. تقوم بإنشاء نموذج – على سبيل المثال، "مستخدم" – وهذا الكائن يعرف بنفسه كيف يقدم نفسه، وكيف يغير الاسم، أو يحسب العمر.
\n\nإليك مثال كلاسيكي في Swift:
\n\nclass User {\n var name: String\n var age: Int\n \n init(name: String, age: Int) {\n self.name = name\n self.age = age\n }\n \n func greet() -> String {\n return "مرحباً، اسمي \\(name) وعمري \\(age) سنة."\n }\n \n func haveBirthday() {\n age += 1\n }\n}\n\nlet user = User(name: "آنا", age: 25)\nuser.haveBirthday()\nprint(user.greet()) // مرحباً، اسمي آنا وعمري 26 سنة.\n\nفي هذا الكود، نستخدم المنهج كائني التوجه في Swift. لدينا حالة (خصائص name, age) يمكن أن تتغير (طريقة haveBirthday). هذا بديهي، خاصة إذا كنت قادماً من Java أو C++. لكن هناك فارق بسيط: الحالة القابلة للتغيير هي مصدر الأخطاء. كلما زاد عدد الكائنات التي تغير بعضها البعض، زادت صعوبة تصحيح البرنامج.
\n\nSwift الوظيفي: قوة الإغلاقات وعدم القابلية للتغيير
\n\nالبرمجة الوظيفية في Swift تقدم نظرة مختلفة. هنا، الدوال هي "مواطنون من الدرجة الأولى". يمكنك تمريرها كمعاملات، وإرجاعها من دوال أخرى، وتخزينها في متغيرات. المبدأ الرئيسي هو الدوال النقية التي لا تغير الحالة الخارجية وتعيد دائماً نفس النتيجة لنفس المدخلات.
\n\nلنرى كيف يبدو نفس المثال بالأسلوب الوظيفي:
\n\nstruct User {\n let name: String\n let age: Int\n}\n\nfunc greet(user: User) -> String {\n return "مرحباً، اسمي \\(user.name) وعمري \\(user.age) سنة."\n}\n\nfunc haveBirthday(user: User) -> User {\n return User(name: user.name, age: user.age + 1)\n}\n\nlet user = User(name: "آنا", age: 25)\nlet olderUser = haveBirthday(user: user)\nprint(greet(user: olderUser)) // مرحباً، اسمي آنا وعمري 26 سنة.\n\nلاحظ: نحن نستخدم هيكلاً (struct) وليس فئة. الهياكل في Swift هي أنواع قيمة. يتم نسخها عند التعيين. الدالة haveBirthday لا تغير الكائن الأصلي، بل تنشئ كائناً جديداً. هذه هي الفكرة الأساسية لـ المنهج الوظيفي – عدم القابلية للتغيير.
مقارنة المنهجين: متى نستخدم أياً منهما؟
\n\nالآن دعنا نقارن بصراحة بين البرمجة كائنية التوجه والبرمجة الوظيفية في Swift. لكل منهما نقاط قوته.
\n\nالمنهج كائني التوجه في Swift
\n\n- \n
- الإيجابيات: بديهي لنمذجة العالم الحقيقي. مناسب تماماً لمكونات واجهة المستخدم (UIViewController, UIView). الوراثة تبسط إعادة استخدام الكود. \n
- السلبيات: قابلية التغيير \n