مونوريبو مع Swift: تنظيم الكود لمشاريع iOS و macOS
في التطوير الحديث لنظامي iOS و macOS، يؤثر اختيار استراتيجية إدارة الكود بشكل مباشر على سرعة التطوير وجودة إعادة الهيكلة وسهولة العمل الجماعي. غالبًا ما يؤدي النهج التقليدي مع العديد من المستودعات المنفصلة (polyrepo) إلى تكرار التبعيات وصعوبات في مزامنة الإصدارات وتجزئة قاعدة الكود. البديل هو المونوريبو (monorepo) — مستودع واحد لجميع الوحدات والمكتبات وتطبيقات المشروع. في هذه المقالة، باستخدام Swift ونظام Apple البيئي كمثال، سنشرح كيفية تنظيم المونوريبو، وما هي الأدوات التي يجب استخدامها، وما هي المخاطر التي يجب مراعاتها.
ما هو المونوريبو ولماذا هو مطلوب في مشاريع Swift
المونوريبو هو استراتيجية لإدارة الإصدارات يتم فيها تخزين جميع أكواد المشروع (عدة تطبيقات ومكتبات وإعدادات) في مستودع Git واحد. في سياق Swift، هذا يعني أنه يمكنك الحصول على ما يلي في مستودع واحد:
- تطبيق iOS (على سبيل المثال،
MyApp) - تطبيق macOS (
MyMacApp) - مكتبة نماذج مشتركة (
CoreModels) - طبقة الشبكات (
Networking) - مكونات واجهة المستخدم (
UIComponents) - الاختبارات ونصوص CI
مزايا المونوريبو لمشاريع Swift:
- إصدار موحد للتبعيات — تستخدم جميع الوحدات نفس الإصدار من المكتبة (على سبيل المثال،
AlamofireأوSwiftUI)، مما يزيل التعارضات. - عمليات commit ذرية — يتم تسجيل التغييرات في API المكتبة واستخدامها في التطبيق في commit واحد، مما يبسط مراجعة الكود والتراجع.
- تبسيط إعادة الهيكلة — يمكنك إعادة تسمية طريقة عامة في وحدة وتصحيح جميع أماكن الاستدعاء فورًا في نفس المستودع.
- CI/CD مشترك — خط أنابيب واحد لبناء واختبار جميع المكونات.
أدوات العمل مع المونوريبو في Swift
في نظام Apple البيئي، هناك أداتان رئيسيتان لتنظيم المونوريبو: Swift Package Manager (SPM) و Tuist. دعنا نلقي نظرة على ميزاتهما.
Swift Package Manager (SPM)
SPM هو مدير حزم مدمج مناسب تمامًا للمونوريبو. يمكنك تعريف الوحدات من خلال Package.swift، ويقوم Xcode تلقائيًا بحل التبعيات. مثال على الهيكل:
MyMonorepo/├── Package.swift├── Sources/│ ├── CoreModels/│ │ └── Models.swift│ ├── Networking/│ │ └── APIClient.swift│ └── UIComponents/│ └── ButtonView.swift├── Apps/│ ├── MyApp/│ │ └── (مشروع iOS)│ └── MyMacApp/│ └── (مشروع macOS)└── Tests/ ├── CoreModelsTests/ └── NetworkingTests/مثال على Package.swift لمثل هذا المونوريبو:
// swift-tools-version:5.9import PackageDescription
let package = Package( name: "MyMonorepo", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library(name: "CoreModels", targets: ["CoreModels"]), .library(name: "Networking", targets: ["Networking"]), .library(name: "UIComponents", targets: ["UIComponents"]), ], dependencies: [ .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.8.0") ], targets: [ .target(name: "CoreModels"), .target( name: "Networking", dependencies: ["CoreModels", "Alamofire"] ), .target( name: "UIComponents", dependencies: ["CoreModels"] ), .testTarget(name: "CoreModelsTests", dependencies: ["CoreModels"]), .testTarget(name: "NetworkingTests", dependencies: ["Networking"]), ])