
في هذه المقالة سأخبرك ما هي مديري الحزم متشابهة في الهيكل الداخلي وخوارزمية التشغيل وما هي اختلافاتهم الأساسية. لقد نظرت إلى مديري الحزم المصممة للتطوير في نظام iOS / OS X ، ولكن محتوى المقالة مع بعض الافتراضات ينطبق على الآخرين.
أصناف من مديري التبعيات
- مديري تبعية النظام - قم بتثبيت الأدوات المساعدة المفقودة في نظام التشغيل. على سبيل المثال ، Homebrew .
- مديرو تبعية اللغة - يجمعون المصادر المكتوبة بإحدى لغات البرمجة في البرامج النهائية القابلة للتنفيذ. على سبيل المثال ، اذهب للبناء .
- مديرو تبعية المشروع - إدارة التبعيات في سياق مشروع معين. أي أن مهامهم تشمل وصف التبعيات وتنزيل وتحديث كود المصدر الخاص بهم. هذه ، على سبيل المثال ، Cocoapods .
والفرق الرئيسي بينهما هو "من يخدمون". نظام MH للمستخدمين ، MH للمشروع للمطورين ، و MH للغة لكليهما.
بعد ذلك ، سأفكر في مديري تبعية المشاريع - نحن نستخدمهم في الغالب ، وهم أسهل في الفهم.
مخطط المشروع عند استخدام مدير التبعية
خذ بعين الاعتبار Cocoapods ،
مدير الحزم الشهير.
عادة نقوم بتنفيذ أمر
تثبيت pod الشرطي ، ثم يقوم مدير التبعية بكل شيء من أجلنا. ضع في اعتبارك ما يجب أن يتكون منه المشروع حتى يكتمل هذا الفريق بنجاح.

- هناك رمزنا الذي نستخدم فيه هذا الاعتماد أو ذاك ، على سبيل المثال ، مكتبة Alamofire .
- من ملف البيان ، يعرف مدير التبعيات ما هي التبعيات التي نستخدمها في شفرة المصدر. إذا نسينا الإشارة إلى أي مكتبة هناك ، فلن يتم إنشاء التبعية ، ولن يتم تجميع المشروع في النهاية.
- ملف القفل - ملف بتنسيق معين تم إنشاؤه بواسطة مدير التبعية ، والذي يسرد جميع التبعيات التي تم تثبيتها بنجاح في المشروع.
- رمز التبعية هو رمز المصدر الخارجي الذي "يسحبه مدير التبعية" والذي سيتم استدعاؤه من رمزنا.
لم يكن هذا ممكنًا بدون خوارزمية محددة يتم تشغيلها في كل مرة بعد أمر تثبيت التبعية.
يتم سرد جميع المكونات الأربعة واحدة تلو الأخرى ، مثل يتكون المكون التالي بناء على المكون السابق.

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

كما ألاحظ أن المطورين مسؤولون عن أول عنصرين - نكتب هذا الرمز ، ومدير التبعية للمكونين المتبقيين - يقوم بإنشاء الملف (الملفات) وتنزيل شفرة المصدر الخاصة بالتبعيات.

سير عمل مدير التبعية
مع فرز المكونات إلى حد ما ، دعنا ننتقل الآن إلى الجزء الخوارزمي من وزارة الصحة.
تبدو خوارزمية العمل النموذجية كما يلي:
- المصادقة على المشروع والبيئة. الكائن المسمى Analyzer مسؤول عن ذلك.
- بناء رسم بياني. من التبعيات ، يجب على وزارة الصحة بناء رسم بياني. يقوم كائن Resolver بذلك.
- تنزيل التبعيات. من الواضح أنه يجب تنزيل شفرة المصدر للاعتمادات حتى نتمكن من استخدامها في مصادرنا.
- تكامل التبعية. قد لا تكون حقيقة أن شفرة مصدر التبعيات تكمن في دليل مجاور على القرص ، لذلك لا تزال بحاجة إلى إرفاقها بمشروعنا.
- تحديث التبعية. لا يتم تنفيذ هذه الخطوة مباشرة بعد الخطوة 4 ، ولكن إذا لزم الأمر ، قم بالترقية إلى الإصدار الجديد من المكتبات. هناك بعض الخصائص المميزة هنا ، لذا فقد قمت بتمييزها في خطوة منفصلة - المزيد عنها لاحقًا.
المصادقة على المشروع والبيئة
يتضمن التحقق من الصحة التحقق من إصدارات نظام التشغيل ، والأدوات المساعدة الإضافية التي يطلبها مدير التبعية ، بالإضافة إلى ربط إعدادات المشروع وملفات البيان: من التحقق من بناء الجملة إلى الإعدادات غير المتوافقة.
عينة
podfilesource 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/RedMadRobot/cocoapods-specs' platform :ios, '10.0' use_frameworks! project 'Project.xcodeproj' workspace 'Project.xcworkspace' target 'Project' do project 'Project.xcodeproj' pod 'Alamofire' pod 'Fabric' pod 'GoogleMaps' end
التحذيرات والأخطاء المحتملة عند فحص ملف podfile:
- لم يتم العثور على تبعية في أي من مستودعات المواصفات ؛
- لم يتم تحديد نظام التشغيل والإصدار بشكل صريح ؛
- مساحة العمل أو اسم المشروع غير صالح.
بناء رسم بياني للتبعية
نظرًا لأن التبعيات التي يتطلبها مشروعنا قد يكون لها تبعيات خاصة بها ، وقد يكون لهذه بدورها تبعيات خاصة بها أو تبعيات فرعية ، فقد استخدم المدير الإصدارات الصحيحة. من الناحية التخطيطية ، يجب أن تصطف جميع التبعيات نتيجة لذلك في
رسم بياني لا دوري موجه .

يقلل إنشاء الرسم البياني الحلقي الموجه من مشكلة الفرز الطوبولوجي. لديها العديد من خوارزميات القرار.
- خوارزمية كان - تعداد القمم ، التعقيد O (n).
- خوارزمية Tarjan - على أساس البحث العميق ، التعقيد O (n).
- خوارزمية Demucron هي قسم رسم بياني متعدد الطبقات.
- خوارزميات متوازية باستخدام عدد متعدد المعالجات. في هذه الحالة ، سيقع التعقيد في O (log (n) ^ 2)
المهمة نفسها هي NP-Complete ؛ يتم استخدام نفس الخوارزمية في المترجمات والتعلم الآلي.
نتيجة الحل هي ملف القفل الذي تم إنشاؤه ، والذي يصف بشكل كامل العلاقة بين التبعيات.

ما المشاكل التي قد تنشأ عندما تعمل هذه الخوارزمية؟ خذ بعين الاعتبار مثال: هناك مشروع مع تبعيات A ، B ، E مع تبعيات متداخلة C ، F ، D.

التبعيات A و B لها تبعية مشتركة C. وهنا C يجب أن تلبي متطلبات التبعيات A و B. يسمح بعض مدير التبعية بتثبيت إصدارات منفصلة إذا لزم الأمر ، ولكن cocoapods ، على سبيل المثال ، لا تفعل ذلك. لذلك ، في حالة عدم توافق المتطلبات: يتطلب A إصدارًا يساوي 2.0 من التبعية C ، و B يتطلب الإصدار 1.0 ، سيفشل التثبيت. وإذا كانت التبعيات A بحاجة إلى الإصدار 1.0 وأعلى إلى الإصدار 2.0 ، والتبعيات B الإصدار 1.2 أو أقل إلى 1.0 ، فسيتم تثبيت الإصدار الأكثر توافقًا للإصدار A و B الإصدار 1.2. لا تنس أنه قد تحدث حالة اعتماد دوري ، حتى لو لم يكن بشكل مباشر - في هذه الحالة ، سيفشل التثبيت أيضًا.

دعونا نرى كيف يبدو في كود مديري التبعيات الأكثر شعبية لنظام iOS.
قرطاج
typealias DependencyGraph = [Dependency: Set<Dependency>] public enum Dependency { /// A repository hosted on GitHub.com or GitHub Enterprise. case gitHub(Server, Repository) /// An arbitrary Git repository. case git(GitURL) /// A binary-only framework case binary(URL) } /// Protocol for resolving acyclic dependency graphs. public protocol ResolverProtocol { init( versionsForDependency: @escaping (Dependency) -> SignalProducer<PinnedVersion, CarthageError>, dependenciesForDependency: @escaping (Dependency, PinnedVersion) -> SignalProducer<(Dependency, VersionSpecifier), CarthageError>, resolvedGitReference: @escaping (Dependency, String) -> SignalProducer<PinnedVersion, CarthageError> ) func resolve( dependencies: [Dependency: VersionSpecifier], lastResolved: [Dependency: PinnedVersion]?, dependenciesToUpdate: [String]? ) -> SignalProducer<[Dependency: PinnedVersion], CarthageError> }
تطبيق Resolver موجود
هنا ، و NewResolver
هنا ، Analyzer على هذا النحو ليس كذلك.
Cocoapods
يتم تخصيص تطبيق خوارزمية الرسم البياني
لمستودع منفصل. هنا تنفيذ
الرسم البياني والمحلل . في
Analyzer ، يمكنك أن تجد أنه يتحقق من تناسق إصدارات cocoapods من النظام وملف القفل.
def validate_lockfile_version! if lockfile && lockfile.cocoapods_version > Version.new(VERSION) STDERR.puts '[!] The version of CocoaPods used to generate ' \ "the lockfile (#{lockfile.cocoapods_version}) is "\ "higher than the version of the current executable (#{VERSION}). " \ 'Incompatibility issues may arise.'.yellow end end
من المصدر ، يمكنك أيضًا رؤية أن محلل يولد أهدافًا للتبعيات.
يبدو ملف قفل cocoapods نموذجي مثل هذا:
PODS: - Alamofire (4.7.0) - Fabric (1.7.5) - GoogleMaps (2.6.0): - GoogleMaps/Maps (= 2.6.0) - GoogleMaps/Base (2.6.0) - GoogleMaps/Maps (2.6.0): - GoogleMaps/Base SPEC CHECKSUMS: Alamofire: 907e0a98eb68cdb7f9d1f541a563d6ac5dc77b25 Fabric: ae7146a5f505ea370a1e44820b4b1dc8890e2890 GoogleMaps: 42f91c68b7fa2f84d5c86597b18ceb99f5414c7f PODFILE CHECKSUM: 5294972c5dd60a892bfcc35329cae74e46aac47b COCOAPODS: 1.4.0
في قسم PODS ، يتم سرد التبعيات المباشرة والمتداخلة مع الإصدارات ، ثم يتم حساب المجموع الاختباري الخاص بها بشكل منفصل ومعا ويشار إلى إصدار cocoapods المستخدم للتثبيت.
تنزيل التبعيات
بعد بناء الرسم البياني بنجاح وإنشاء ملف القفل ، يستمر مدير التبعية في تنزيلها. ليس بالضرورة أنه سيكون رمز المصدر ، يمكن أن يكون أيضًا ملفات قابلة للتنفيذ أو أطر عمل مجمعة. أيضًا ، يدعم جميع مديري التبعيات بشكل عام القدرة على التثبيت على مسار محلي.

لا يوجد شيء معقد لتنزيلها من الرابط (الذي بالطبع تحتاج إلى الحصول عليه من مكان ما) ، لذلك لن أخبرك كيف يحدث التنزيل نفسه ، ولكن التركيز على مشكلات المركزية والأمن.
المركزية
بعبارات بسيطة ، لدى مدير التبعية طريقتان عند تنزيل التبعيات:
- انتقل إلى قائمة التبعيات المتوفرة واحصل على رابط التنزيل بالاسم.
- يجب أن نحدد مصدر كل تبعية بشكل صريح في ملف البيان.
يسير مديرو التبعية المركزية على المسار الأول ، ولا مركزيون على طول المسار الثاني.

الأمان
إذا قمت بتنزيل التبعيات عبر https أو ssh ، فيمكنك النوم بسلام. ومع ذلك ، غالبًا ما يقدم المطورون روابط http إلى مكتباتهم الرسمية. وقد نواجه هنا هجوم
رجل في المنتصف عندما ينتحل مهاجم الكود المصدري أو الملف القابل للتنفيذ أو الإطار. بعض مديري التبعيات غير محميين من هذا ، والبعض يفعل ذلك على النحو التالي.
البيرة
التحقق من تجعيد الإصدارات القديمة من OS X.
def check_for_bad_curl return unless MacOS.version <= "10.8" return if Formula["curl"].installed? <<~EOS The system curl on 10.8 and below is often incapable of supporting modern secure connections & will fail on fetching formulae. We recommend you: brew install curl EOS end
يوجد أيضًا
فحص تجزئة SHA256 عند التنزيل عبر http.
def curl_http_content_headers_and_checksum(url, hash_needed: false, user_agent: :default) max_time = hash_needed ? "600" : "25" output, = curl_output( "--connect-timeout", "15", "--include", "--max-time", max_time, "--location", url, user_agent: user_agent ) status_code = :unknown while status_code == :unknown || status_code.to_s.start_with?("3") headers, _, output = output.partition("\r\n\r\n") status_code = headers[%r{HTTP\/.* (\d+)}, 1] end output_hash = Digest::SHA256.digest(output) if hash_needed { status: status_code, etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2], content_length: headers[/Content-Length: (\d+)/, 1], file_hash: output_hash, file: output, } end
ويمكنك أيضًا تعطيل عمليات إعادة التوجيه غير الآمنة إلى http (متغير
HOMEBREW_NO_INSECURE_REDIRECT ).
قرطاج و Cocoapods
كل شيء أبسط هنا -
لا يمكنك استخدام http على الملفات القابلة للتنفيذ.
guard binaryURL.scheme == "file" || binaryURL.scheme == "https" else { return .failure(BinaryJSONError.nonHTTPSURL(binaryURL)) }
def validate_source_url(spec) return if spec.source.nil? || spec.source[:http].nil? url = URI(spec.source[:http]) return if url.scheme == 'https' || url.scheme == 'file' warning('http', "The URL (`#{url}`) doesn't use the encrypted HTTPs protocol. " \ 'It is crucial for Pods to be transferred over a secure protocol to protect your users from man-in-the-middle attacks. '\ 'This will be an error in future releases. Please update the URL to use https.') end
الرمز الكامل
هنا .
مدير حزمة Swift
في الوقت الحالي ، لا يمكن العثور على أي شيء متعلق بالأمان ، ولكن في مقترحات التطوير هناك إشارة قصيرة إلى
آلية لتوقيع الحزم باستخدام الشهادات.
تكامل التبعية
من خلال التكامل ، أعني ربط التبعيات بالمشروع بطريقة يمكننا استخدامها بحرية ، ويتم تجميعها مع رمز التطبيق الرئيسي.
يمكن أن يكون التكامل إما يدويًا (قرطاج) أو تلقائي (Cocoapods). مزايا التلقائي هي الحد الأدنى من الإيماءات من قبل المطور ، ولكن يمكن إضافة الكثير من السحر إلى المشروع.
تختلف بعد تثبيت التبعيات في مشروع باستخدام Cocoapods في حالة الدليل ، يمكنك ، على سبيل المثال ، باتباع إرشادات قرطاج
هذه ، التحكم الكامل في عملية إضافة التبعيات إلى المشروع. موثوقة ، لكنها أطول.
تحديث التبعية
يمكنك التحكم في التعليمات البرمجية المصدر للتبعيات في المشروع باستخدام إصداراتها.
هناك 3 طرق مستخدمة في مديري التبعيات:
- إصدارات المكتبة. الطريقة الأكثر ملاءمة وشائعة. يمكنك تحديد إصدار محدد وفاصل زمني. إنها طريقة يمكن التنبؤ بها تمامًا لدعم توافق التبعية ، شريطة أن يقوم المؤلفون بتأسيس المكتبات بشكل صحيح.
- الفرع. عند تحديث فرع وإجراء مزيد من التحديث على التبعية ، لا يمكننا التنبؤ بالتغييرات التي ستحدث.
- الالتزام أو الوسم. عند تنفيذ أمر التحديث ، لن يتم تحديث التبعيات التي تحتوي على ارتباطات إلى التزام أو علامة معينة (إذا لم يتم تغييرها).
الخلاصة
في المقال ، أعطيت فهمًا سطحيًا للبنية الداخلية لمديري التبعيات. إذا كنت تريد معرفة المزيد ، فيجب أن تتعمق في شفرة المصدر لمدير الحزم. أسهل طريقة للعثور على واحدة مكتوبة بلغة مألوفة. المخطط الموصوف نموذجي ، ولكن في مدير تبعية معين قد يكون هناك شيء مفقود أو ، على العكس من ذلك ، قد يظهر مخطط جديد.
التعليقات والمناقشة في التعليقات هي موضع ترحيب.