مراجعة الكود في Swift: ما الذي يجب التحقق منه وكيفية تقديم الملاحظات
مراجعة الكود ليست مجرد إجراء شكلي، بل هي أداة قوية لتحسين جودة الكود والنمو المهني للفريق. بالنسبة لمطوري iOS/macOS الذين يستخدمون Swift، فإن المراجعة المنفذة بشكل جيد تساعد في تجنب الأخطاء البرمجية، وتحسين البنية، والحفاظ على نمط كود موحد. في هذا المقال، سنشرح ما الذي يجب الانتباه إليه عند مراجعة كود مشاريع Swift، وكيفية تقديم ملاحظات مفيدة بدلاً من أن تكون محبطة.
1. البنية وتقسيم المسؤوليات
أول ما يجب تقييمه أثناء المراجعة هو مدى توافق الكود مع البنية المختارة (MVC, MVVM, VIPER, SwiftUI + Combine). البنية السيئة تؤدي إلى "كائنات الله" (God-Objects) وصعوبة في الصيانة.
ما الذي يجب التحقق منه:
- هل يخلط ViewController بين منطق الأعمال وكود واجهة المستخدم (UI)؟
- هل تم فصل منطق الشبكة في خدمات منفصلة (مثل NetworkService)؟
- هل يتم استخدام البروتوكولات (Protocols) لتجريد التبعيات؟
- هل هناك مسؤوليات كثيرة جداً موكلة إلى فئة واحدة؟
// ❌ سيء: ViewController يعرف URLSession ويقوم بتحليل JSONclass UserViewController: UIViewController { func fetchUser() { URLSession.shared.dataTask(with: URL(string: "https://api.example.com/user")!) { data, _, _ in let user = try? JSONDecoder().decode(User.self, from: data!) DispatchQueue.main.async { self.updateUI(with: user) } }.resume() }}
// ✅ جيد: المنطق تم فصله في خدمةprotocol UserServiceProtocol { func fetchUser(completion: @escaping (Result<User, Error>) -> Void)}
class UserViewModel { private let userService: UserServiceProtocol init(userService: UserServiceProtocol) { self.userService = userService } func loadUser() { userService.fetchUser { [weak self] result in // معالجة النتيجة } }}نصيحة حول تقديم الملاحظات: بدلاً من قول "هذه الفئة كبيرة جداً"، اكتب: "أرى أن UserViewController مسؤول عن طلبات الشبكة وواجهة المستخدم معاً. ربما يمكننا فصل الطلب إلى خدمة منفصلة، كما ناقشنا في جلسة الاستعراض؟ هذا سيسهل عملية الاختبار".
2. أمان الذاكرة وإدارة دورة الحياة
Swift هي لغة مع العد التلقائي للمراجع (ARC)، لكن هذا لا يعفي المطور من الاهتمام بدورات المراجع القوية. الأخطاء في هذا المجال هي سبب شائع لتسرب الذاكرة في تطبيقات iOS.
ما الذي يجب التحقق منه:
- هل يتم استخدام
[weak self]أو[unowned self]في الإغلاقات (Closures)، خاصة عند العمل مع async/await و Combine؟ - هل يتم إنشاء مرجع دائري (Cyclic Reference) بين المفوض (Delegate) والمالك؟
- هل يتم تحرير الموارد بشكل صحيح (المراقبون، المؤقتات)؟
// ❌ تسرب محتمل: مرجع قوي لـ self داخل الإغلاقclass LocationManager { var onLocationUpdate: ((CLLocation) -> Void)? func startUpdating() { someAsyncAPI { location in self.onLocationUpdate?(location) // تم القبض على self بقوة } }}
// ✅ تم الإصلاح باستخدام [weak self]class LocationManager { var onLocationUpdate: ((CLLocation) -> Void)? func startUpdating() { someAsyncAPI { [weak self] location in guard let self = self else { return } self.onLocationUpdate?(location) } }}نصيحة حول تقديم الملاحظات: لا تشير فقط إلى المشكلة، بل اذكر العواقب أيضاً: "قد يحدث هنا تسرب للذاكرة إذا كان LocationManager سيعيش لفترة أطول من اللازم. دعنا نضيف [weak self] لكسر الدورة".
3. معالجة الأخطاء والقيم الاختيارية (Optionals)
Swift هي لغة ذات كتابة صارمة ونظام قوي للقيم الاختيارية (Optional). المعالجة السيئة للقيم الاختيارية هي أحد أكبر