مبادئ SOLID في Swift: النظرية والتطبيق لمطوري iOS المتقدمين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا تعتبر مبادئ SOLID مهمة لمطور Swift

\n

في عالم تطوير iOS، يعد إنشاء كود قابل للصيانة والتوسع مهمة رئيسية. تظل مبادئ SOLID، التي صاغها روبرت مارتن، المعيار الذهبي لهندسة البرمجيات. على المستوى المتقدم، يتيح إتقان هذه المبادئ في Swift ليس فقط كتابة كود نظيف، بل أيضًا بناء أنظمة مرنة قادرة على تحمل تغييرات المتطلبات. في هذه المقالة، سنحلل كل مبدأ مع أمثلة بلغة Swift، مع التركيز على المهام الواقعية لمطور iOS/macOS.

\n\n

1. مبدأ المسؤولية الفردية (SRP) في Swift

\n

النظرية: يجب أن يكون لكل فئة أو هيكل سبب واحد فقط للتغيير. عمليًا، هذا يعني أن الوحدة مسؤولة عن مهمة واحدة محددة بوضوح.

\n\n

المشكلة: ViewController مثقل بالمهام

\n

في UIKit، غالبًا ما توجد وحدات تحكم تدير واجهة المستخدم وتعالج طلبات الشبكة وتحفظ البيانات في نفس الوقت. هذا ينتهك مبدأ SRP.

\n
// ❌ انتهاك SRP\nclass UserViewController: UIViewController {\n    @IBOutlet weak var tableView: UITableView!\n    private var users: [User] = []\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        fetchUsers()\n    }\n\n    private func fetchUsers() {\n        // طلب شبكة\n        URLSession.shared.dataTask(with: URL(string: "https://api.example.com/users")!) { data, _, _ in\n            // تحليل JSON\n            // حفظ في Core Data\n            DispatchQueue.main.async {\n                self.tableView.reloadData()\n            }\n        }.resume()\n    }\n}
\n\n

الحل: فصل المسؤوليات

\n

نقوم بنقل التعامل مع البيانات والشبكة إلى خدمات منفصلة.

\n
// ✅ SRP: خدمة منفصلة للتعامل مع المستخدمين\nprotocol UserServiceProtocol {\n    func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void)\n}\n\nclass UserService: UserServiceProtocol {\n    func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void) {\n        // منطق طلب الشبكة\n    }\n}\n\n// ✅ SRP: مدير منفصل لـ Core Data\nclass CoreDataManager {\n    func saveUsers(_ users: [User]) {\n        // حفظ في Core Data\n    }\n}\n\n// ✅ SRP: ViewController يدير واجهة المستخدم فقط\nclass UserViewController: UIViewController {\n    private let userService: UserServiceProtocol\n    private let coreDataManager: CoreDataManager\n\n    init(userService: UserServiceProtocol, coreDataManager: CoreDataManager) {\n        self.userService = userService\n        self.coreDataManager = coreDataManager\n        super.init(nibName: nil, bundle: nil)\n    }\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        loadUsers()\n    }\n\n    private func loadUsers() {\n        userService.fetchUsers { [weak self] result in\n            switch result {\n            case .success(let users):\n                self?.coreDataManager.saveUsers(users)\n                self?.updateUI(with: users)\n            case .failure(let error):\n                self?.showError(error)\n            }\n        }\n    }\n}
\n\n

2. مبدأ الانفتاح/الإغلاق (OCP) وبروتوكولات Swift

\n

النظرية: يجب أن تكون الكيانات البرمجية (الفئات، الوحدات) مفتوحة للتمديد ولكن مغلقة للتعديل. في Swift، يتم تحقيق ذلك من خلال البروتوكولات والوراثة.

\n\n

مثال: نظام الإشعارات

\n
// ❌ انتهاك OCP: عند إضافة نوع جديد من الإشعارات، يجب تغيير switch\nclass NotificationSender {\n    func send(_ notification: Notification, type: String) {\n        switch type {\n        case "email":\n            // إرسال بريد إلكتروني\n        case "push":\n            // إرسال إشعار فوري\n        default:\n            break\n        }\n    }\n}\n\n// ✅ OCP: استخدام بروتوكول\nprotocol NotificationChannel {\n    func send(_ notification: Notification)\n}\n\nclass EmailChannel: NotificationChannel {\n    func send(_ notification: Notification)                

المدونات

توصيات الكتب