إعادة هيكلة الكود القديم بلغة Swift: من الألف إلى الياء
\nالعمل مع الكود القديم (legacy code) هو جزء لا مفر منه في حياة مطور iOS/macOS. غالبًا ما يكون هذا الكود مكتوبًا بإصدارات قديمة من Swift أو حتى Objective-C، خاليًا من الاختبارات، مع "أرقام سحرية" و UIViewController ضخمة. في هذه المقالة، سنقوم بتحليل استراتيجية خطوة بخطوة لإعادة هيكلة هذا الكود، وتحويله إلى مشروع حديث، قابل للصيانة والاختبار.
1. التحضير والأمان: قبل لمس الكود
\nأهم قاعدة في إعادة الهيكلة: لا تكسر ما يعمل. بدون اختبارات، أي تغيير هو قفزة في المجهول.
\n- \n
- تغطية بالاختبارات (Characterization Tests): اكتب اختبارات تثبت السلوك الحالي. حتى لو بدا الكود خاطئًا، قم أولاً بتوثيق عمله. \n
- نظام التحكم بالإصدارات: قم بعمل commit للحالة الحالية. استخدم feature branch. \n
- الأدوات: Xcode مع
Edit > Refactor(Rename, Extract Method)، بالإضافة إلى أدوات التحليل (SwiftLint) لضمان نمط موحد. \n
// مثال "تجميد" السلوك لطريقة قديمة\nclass LegacyCalculator {\n func calculateTotal(items: [Int]) -> Int {\n // منطق قديم غير قابل للقراءة\n var result = 0\n for i in items {\n result += i * 2\n }\n return result + 10\n }\n}\n\n// اختبار يثبت السلوك\nfunc testCalculateTotal() {\n let sut = LegacyCalculator()\n let result = sut.calculateTotal(items: [1, 2, 3])\n XCTAssertEqual(result, 22) // (1+2+3)*2 + 10 = 22\n}\n\n\n2. استراتيجية "كبش الفداء": المتغيرات العامة و Singleton
\nيشتهر الكود القديم بحالاته العامة و Singleton. هذا يجعل الكود مقترنًا بشدة وغير قابل للتنبؤ.
\nالمشكلة:
\nclass NetworkManager {\n static let shared = NetworkManager()\n var baseURL: String = "http://old.api.com"\n func fetchData() { ... }\n}\n\nالحل: حقن التبعيات (Dependency Injection). نقوم بإنشاء بروتوكول وتمرير التبعيات عبر المُهيئ.
\nprotocol NetworkService {\n func fetchData()\n}\n\nclass ModernViewModel {\n private let network: NetworkService\n \n init(network: NetworkService) {\n self.network = network\n }\n \n func load() {\n network.fetchData()\n }\n}\n\nهذا النهج يسمح بتبديل الخدمات بسهولة في الاختبارات ويجعل الكود معياريًا.
\n\n3. مكافحة "وحدة التحكم الضخمة" (Massive View Controller)
\nكلاسيكيات iOS القديمة: UIViewController الذي يتحمل كل شيء - من طلبات الشبكة إلى تنسيق واجهة المستخدم. تتم إعادة الهيكلة من خلال فصل المسؤوليات (SRP).
الخطوة 1: افصل منطق الأعمال في نموذج منفصل (ViewModel).
\n// كان في وحدة التحكم\nfunc buttonTapped() {\n let data = fetchData()\n let total = data.reduce(0, +)\n label.text = "المجموع: \\(total)"\n}\n\n// أصبح: ViewModel\nclass MyViewModel {\n func calculateTotal(data: [Int]) -> String {\n let total = data.reduce(0, +)\n return "المجموع: \\(total)"\n }\n}\n\n\nالخطوة 2: انقل إعداد واجهة المستخدم إلى طرق أو مصانع منفصلة.
\n- \n
- أنشئ فئة
ViewBuilderللتسلسلات الهرمية المعقدة. \n - استخدم
UICollectionViewDiffableDataSourceبدلاً منdataSourceالقديم. \n
4. التحديث: من Objective-C إلى Swift وواجهات برمجة التطبيقات الجديدة
\nغالبًا ما يحتوي الكود القديم على مزيج من Objective-C و Swift. عند إعادة الهيكلة، من المهم تحديث الهياكل القديمة:
\n\n- \n
- استبدال
NSErrorبـthrows: يستخدم Swift الحديث الاستثناءات لمعالجة الأخطاء. \n - التخلي عن
!(