الكود النظيف في Swift: لماذا يحتاجه مطورو iOS
كل مطور واجه موقفًا حيث يتحول الكود القديم إلى "سباجيتي" بعد شهر. في عالم Swift، حيث تنمو المشاريع بسرعة، يصبح الحفاظ على نظافة الكود أمرًا بالغ الأهمية. الكود النظيف ليس مجرد جماليات، بل أداة توفر ساعات من التصحيح وتبسط إضافة ميزات جديدة. في هذه المقالة، سنقوم بتحليل المبادئ الرئيسية للكود النظيف كما تطبق على Swift، مع أمثلة حقيقية لنظامي iOS وmacOS.
1. التسمية: قابلية القراءة أولاً
التسمية الصحيحة هي أساس الكود النظيف. في Swift، حيث غالبًا ما تكون واجهات برمجة التطبيقات (APIs) موثقة ذاتيًا، تعتبر الأسماء السيئة المصدر الرئيسي للارتباك.
مثال سيء:
class DataManager { func getData() -> [String: Any] { // ... }}مثال جيد:
class UserProfileFetcher { func fetchUserProfile(for userID: String) -> Result<UserProfile, NetworkError> { // ... }}- استخدم الأفعال للطرق (fetch, update, delete).
- تجنب الاختصارات — vc, btn, str هي من الماضي.
- المتغيرات المنطقية يجب أن تُقرأ كجمل:
isLoggedIn,hasNetworkConnection.
2. الدوال: صغيرة وذات غرض واحد
في Swift، حيث تحظى closures والبرمجة الوظيفية بشعبية، من السهل الانجراف وكتابة دالة ضخمة. مبدأ المسؤولية الواحدة يعمل بنسبة 100% هنا.
مثال سيء:
func processUserData(user: User) { // Validation if user.email.isEmpty { return } // Save to CoreData CoreDataStack.shared.save(user) // Send to server APIClient.shared.send(user) // Update UI DispatchQueue.main.async { self.tableView.reloadData() }}مثال جيد (تقسيم إلى دوال صغيرة):
func processUserData(user: User) { guard validateUser(user) else { return } saveUserLocally(user) sendUserToServer(user) updateUI()}
private func validateUser(_ user: User) -> Bool { return !user.email.isEmpty}
private func saveUserLocally(_ user: User) { CoreDataStack.shared.save(user)}
private func sendUserToServer(_ user: User) { APIClient.shared.send(user)}
private func updateUI() { DispatchQueue.main.async { self.tableView.reloadData() }}قاعدة الـ 20 سطرًا: إذا كانت الدالة لا تتناسب مع الشاشة — قم بتقسيمها. يجب أن تقوم كل دالة بشيء واحد فقط.
3. SOLID في Swift: أمثلة عملية
مبادئ SOLID ليست تجريدًا، بل أدوات عمل. دعنا نحلل اثنين منها الرئيسيين لنظام iOS.
مبدأ الانفتاح/الإغلاق
يجب أن تكون الفئات مفتوحة للتمديد ولكن مغلقة للتعديل. بدلاً من تغيير فئة جاهزة، استخدم البروتوكولات.
protocol PaymentProcessor { func process(amount: Double, currency: String) -> Bool}
class ApplePayProcessor: PaymentProcessor { func process(amount: Double, currency: String) -> Bool { // Apple Pay logic return true }}
class StripeProcessor: PaymentProcessor { func process(amount: Double, currency: String) -> Bool { // Stripe logic return true }}
// Now adding a new payment method is simple — just create a new class without touching the old ones.مبدأ استبدال ليسكوف
يجب ألا تكسر الفئات الفرعية منطق الفئة الأم. الخطأ الشائع هو تجاوز دالة وتغيير عقدها.
class Vehicle { func startEngine() { print("Engine started") }}
class ElectricCar: Vehicle { override func startEngine() { // Violation: el