مستودع واحد مع Swift: تنظيم الكود لنظامي iOS وmacOS

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

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

ابدأ الدورة

مقدمة: لماذا المستودع الأحادي في Swift؟



غالبًا ما يواجه التطوير لنظامي iOS وmacOS معضلة: كيف ننظم الكود بحيث يظل قابلاً للتوسع وإعادة الاستخدام وسهل الصيانة؟ يؤدي النهج التقليدي مع العديد من المستودعات المنفصلة (multi-repo) إلى التجزئة، وتكرار التبعيات، وصعوبات في تنسيق التغييرات. الحل هو المستودع الأحادي (monorepo).



المستودع الأحادي هو مستودع واحد يحتوي على جميع مكونات المشروع: التطبيقات، المكتبات، أدوات البناء، والتكوينات. بالنسبة لنظام Swift البيئي، هذا النهج مهم بشكل خاص بفضل Swift Package Manager (SPM)، الذي يدعم بشكل ممتاز الحزم المحلية والهندسة المعمارية المعيارية منذ الإصدار 5.3+.



في هذه المقالة، سنشرح كيفية تنظيم مستودع أحادي لمشاريع Swift، وسننظر في الهيكل، والأدوات (Tuist, XcodeGen)، وأفضل الممارسات مع أمثلة الكود.



1. مزايا المستودع الأحادي لـ Swift



قبل الانتقال إلى التنفيذ، دعنا نلقي نظرة على المزايا الرئيسية:



  • إصدار موحد للتبعيات — تستخدم جميع الوحدات نفس الإصدار من المكتبات، مما يستبعد التعارضات.
  • الالتزامات الذرية — التغيير في API في حزمة واحدة ينعكس فورًا على جميع الوحدات التابعة، دون الحاجة إلى مزامنة بين المستودعات.
  • تبسيط CI/CD — خط أنابيب واحد، تكوين واحد، تخزين مؤقت للبناءات.
  • إعادة استخدام الكود — الأدوات المساعدة المشتركة، النماذج، طبقات الشبكة متاحة بسهولة لجميع الأهداف (iOS, macOS, watchOS).
  • مراجعة الكود — التغييرات في أجزاء مختلفة من المشروع مرئية في PR واحد.


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



2. هيكل المستودع الأحادي في Swift



لنلقِ نظرة على هيكل نموذجي لمشروع يتضمن تطبيق iOS وتطبيق macOS مع مكتبة مشتركة:



MyProject/├── Apps/│   ├── iOSApp/│   │   ├── Sources/│   │   │   └── AppDelegate.swift│   │   ├── Resources/│   │   └── Package.swift│   └── macOSApp/│       ├── Sources/│       │   └── AppDelegate.swift│       ├── Resources/│       └── Package.swift├── Packages/│   ├── Core/│   │   ├── Sources/│   │   │   ├── Core.swift│   │   │   └── Extensions/│   │   ├── Tests/│   │   └── Package.swift│   ├── Networking/│   │   ├── Sources/│   │   │   └── NetworkManager.swift│   │   ├── Tests/│   │   └── Package.swift│   └── UIComponents/│       ├── Sources/│       │   └── CustomButton.swift│       ├── Tests/│       └── Package.swift├── Tools/│   └── Scripts/│       └── build.sh├── .github/│   └── workflows/│       └── ci.yml├── Package.swift (جذر)├── Tuist.swift (إذا كنا نستخدم Tuist)└── README.md


شرح الهيكل:

  • Apps/ — دليل التطبيقات النهائية. كل تطبيق هو حزمة Swift منفصلة تعتمد على الحزم من Packages/.
  • Packages/ — جميع المكتبات والوحدات الداخلية. كل حزمة لها Package.swift الخاص بها ويمكن اختبارها بشكل مستقل.
  • Tools/ — نصوص البناء، أدوات التحليل، توليد الكود.
  • Package.swift الجذر (أو تكوين Tuist/XcodeGen) — يصف مساحة العمل والروابط بين الحزم.


2.1 مثال على Package.swift الجذر (SPM)



// swift-tools-version:5.9import PackageDescription

let package = Package( name: "MyProject", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library(name: "Core", targets: ["Core"]), .library(name: "Networking", targets: ["Networking"]), .library(name: "UICompon

المدونات

توصيات الكتب