تكلفة الملاءمة
يعد تصميم محرر أكواد يمكن للطيف من المشاريع الصغيرة إلى الكبيرة الحجم استخدامه مهمة صعبة. تتعامل العديد من الأدوات مع المشكلة من خلال وضع حلها في طبقات وتوفير قابلية التوسعة. الطبقة السفلية منخفضة المستوى للغاية وقريبة من نظام البناء الأساسي، والطبقة العلوية عبارة عن تجريد عالي المستوى مناسب للاستخدام ولكنه أقل مرونة. وبذلك، يجعلون الأشياء البسيطة سهلة، وكل شيء آخر ممكن.
ومع ذلك، [Apple] (https://www.apple.com) قررت Apple اتباع نهج مختلف مع Xcode. السبب غير معروف، ولكن من المحتمل أن تحسينها لمواجهة تحديات المشاريع الكبيرة لم يكن هدفهم أبدًا. لقد استثمروا بشكل مفرط في توفير الراحة للمشاريع الصغيرة، ووفروا القليل من المرونة، وربطوا الأدوات بقوة مع نظام البناء الأساسي. ولتحقيق الملاءمة، قدموا افتراضيات معقولة، والتي يمكنك استبدالها بسهولة، وأضافوا الكثير من السلوكيات الضمنية التي تم حلها في وقت الإنشاء والتي هي السبب في العديد من المشكلات على نطاق واسع.
الوضوح والمقياس
عند العمل على نطاق واسع، الشرح هو المفتاح. فهو يسمح لنظام الإنشاء بتحليل وفهم بنية المشروع وتبعياته في وقت مبكر، وإجراء التحسينات التي قد تكون مستحيلة لولا ذلك. نفس هذه الصراحة هي أيضًا أساسية في ضمان عمل ميزات المحرر مثل [معاينات SwiftUI] (https://developer.apple.com/documentation/swiftui/previews-in-xcode) أو [وحدات سويفت ماكرو] (https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros/) بشكل موثوق ومتوقع. نظرًا لأن مشاريع Xcode و Xcode تبنّت الشهادة الضمنية كخيار تصميم صالح لتحقيق الراحة، وهو مبدأ ورثه مدير حزم Swift، فإن صعوبات استخدام Xcode موجودة أيضًا في مدير حزم Swift.
عن دور المعلم
يمكن أن نلخص دور تويست كأداة تمنع المشاريع المحددة ضمنيًا وتستفيد من الصراحة لتوفير تجربة أفضل للمطورين (مثل عمليات التحقق من الصحة والتحسينات). أدوات مثل [Bazel] (https://bazel.build) تأخذها إلى أبعد من ذلك من خلال نقلها إلى مستوى نظام البناء.
هذه مشكلة بالكاد نوقشت في المجتمع، لكنها مشكلة كبيرة. أثناء عملنا على تويست، لاحظنا أن العديد من المؤسسات والمطورين يعتقدون أن التحديات الحالية التي يواجهونها ستتم معالجتها بواسطة [Swift Package Manager] (https://www.swift.org/documentation/package-manager/)، ولكن ما لا يدركونه هو أنه نظرًا لأنه مبني على نفس المبادئ، على الرغم من أنه يخفف من تعارضات Git المعروفة جدًا، إلا أنه يقلل من تجربة المطورين في مجالات أخرى ويستمر في جعل المشاريع غير قابلة للتحسين.
في الأقسام التالية، سنناقش بعض الأمثلة الحقيقية لكيفية تأثير الشاهد الضمني على تجربة المطور وصحة المشروع. القائمة ليست شاملة، ولكن يجب أن تعطيك فكرة جيدة عن التحديات التي قد تواجهك عند العمل مع مشاريع Xcode أو حزم Swift.
الراحة تعترض طريقك
دليل المنتجات المبنية المشتركة
يستخدم Xcode دليلاً داخل دليل البيانات المشتقة لكل منتج. في داخله، يخزن داخله القطع الأثرية للبناء، مثل الثنائيات المترجمة وملفات dSYM والسجلات. نظرًا لأن جميع منتجات المشروع تذهب إلى نفس الدليل، والذي يكون مرئيًا افتراضيًا من الأهداف الأخرى للربط ضدها، قد ينتهي بك الأمر بأهداف تعتمد ضمنيًا على بعضها البعض. في حين أن هذا قد لا يمثل مشكلة عند وجود عدد قليل من الأهداف، إلا أنه قد يظهر على شكل إنشاءات فاشلة يصعب تصحيحها عندما ينمو المشروع.
تتمثل نتيجة قرار التصميم هذا في أن العديد من المشاريع يتم تجميعها بشكل عرضي برسم بياني غير محدد بشكل جيد.
اكتشاف التبعات الضمنية
يوفر تويست أمرًا
أمرًا للكشف عن التبعيات الضمنية. يمكنك استخدام هذا الأمر للتحقق في CIمن أن جميع التبعيات صريحة في CI.
ابحث عن التبعيات الضمنية في المخططات
يصبح تحديد الرسم البياني للتبعية والحفاظ عليه في Xcode أكثر صعوبة مع نمو المشروع. إنه أمر صعب لأنه يتم تدوينها في ملفات .pbxproj كمراحل بناء وإعدادات بناء، ولا توجد أدوات لتصور الرسم البياني والعمل معه، وقد تتطلب التغييرات في الرسم البياني (مثل إضافة إطار عمل ديناميكي جديد مُجمَّع مسبقًا)، تغييرات في التكوين في المنبع (مثل إضافة مرحلة بناء جديدة لنسخ إطار العمل إلى الحزمة).
قررت شركة Apple في مرحلة ما أنه بدلاً من تطوير نموذج الرسم البياني إلى شيء أكثر قابلية للإدارة، سيكون من المنطقي إضافة خيار لحل التبعيات الضمنية في وقت الإنشاء. هذا مرة أخرى خيار تصميم مشكوك فيه لأنك قد ينتهي بك الأمر بأوقات بناء أبطأ أو إنشاءات غير متوقعة. على سبيل المثال، قد تنجح عملية الإنشاء محليًا بسبب بعض الحالات في اشتقاق البيانات، والتي تعمل كـ [مفرد] (https://en.wikipedia.org/wiki/Singleton_pattern)، ولكن قد تفشل بعد ذلك في التحويل البرمجي على CI لأن الحالة مختلفة.
TIP
نوصي بتعطيل ذلك في مخططات مشروعك، واستخدام مثل Tuist الذي يسهل إدارة الرسم البياني للتبعية.
معاينات SwiftUI والمكتبات/الأطر الثابتة
تتطلب بعض ميزات المحرر مثل SwiftUI Previews أو Swift Macros تجميع الرسم البياني للتبعية من الملف الذي يتم تحريره. يتطلب هذا التكامل بين المحرر أن يقوم نظام الإنشاء بحل أي تضمين وإخراج القطع الأثرية الصحيحة الضرورية لعمل تلك الميزات. كما يمكنك أن تتخيل، كلما كان الرسم البياني ضمنيًا، زادت صعوبة المهمة بالنسبة لنظام الإنشاء ، وبالتالي ليس من المستغرب أن العديد من هذه الميزات لا تعمل بشكل موثوق. غالبًا ما نسمع من المطورين أنهم توقفوا عن استخدام معاينات SwiftUI منذ فترة طويلة لأنها غير موثوقة للغاية. وبدلاً من ذلك، فإنهم يستخدمون إما تطبيقات نموذجية، أو يتجنبون أشياء معينة، مثل استخدام المكتبات الثابتة أو مراحل بناء البرامج النصية، لأنها تتسبب في تعطل الميزة.
مكتبات قابلة للدمج
على الرغم من أن الأطر الديناميكية أكثر مرونة وأسهل في العمل معها، إلا أن لها تأثيرًا سلبيًا في وقت تشغيل التطبيقات. على الجانب الآخر، تكون المكتبات الثابتة أسرع في التشغيل، لكنها تؤثر على وقت التجميع ويكون العمل معها أصعب قليلاً، خاصةً في سيناريوهات الرسوم البيانية المعقدة. ألن يكون من الرائع لو كان بإمكانك التغيير بين هذا أو ذاك اعتمادًا على التكوين؟ لا بد أن هذا ما فكرت فيه Apple عندما قررت العمل على مكتبات قابلة للدمج. ولكن مرة أخرى، نقلوا المزيد من الاستدلال في وقت الإنشاء إلى وقت الإنشاء. إذا كان الاستدلال على الرسم البياني للتبعية، تخيل الاضطرار إلى القيام بذلك عندما يتم حل الطبيعة الثابتة أو الديناميكية للهدف في وقت الإنشاء بناءً على بعض إعدادات الإنشاء في بعض الأهداف. حظًا موفقًا في جعل ذلك يعمل بشكل موثوق مع ضمان عدم تعطل ميزات مثل معاينات SwiftUI.
يأتي العديد من المستخدمين إلى تويست راغبين في استخدام المكتبات القابلة للدمج وإجابتنا هي نفسها دائمًا. لست بحاجة إلى ذلك. يمكنك التحكم في الطبيعة الثابتة أو الديناميكية لأهدافك في وقت الإنشاء مما يؤدي إلى مشروع يكون رسمه البياني معروفًا قبل التجميع. لا تحتاج إلى حل أي متغيرات في وقت الإنشاء.
bash
# The value of TUIST_DYNAMIC can be read from the project {#the-value-of-tuist_dynamic-can-be-read-from-the-project}
# to set the product as static or dynamic based on the value. {#to-set-the-product-as-static-or-dynamic-based-on-the-value}
TUIST_DYNAMIC=1 tuist generateصريح وصريح وصريح وصريح
إذا كان هناك مبدأ مهم غير مكتوب نوصي به كل مطور أو مؤسسة تريد تطويرها باستخدام Xcode لتوسيع نطاقها، فهو أن عليهم تبني الصراحة. وإذا كان من الصعب إدارة الشهود الصريح مع مشاريع Xcode الخام، فعليهم التفكير في شيء آخر، إما [تويست] (https://tuist.io) أو [بازل] (https://bazel.build). عندها فقط ستكون الموثوقية والقدرة على التنبؤ والتحسينات ممكنة.
المستقبل
من غير المعروف ما إذا كانت أبل ستفعل شيئًا لمنع جميع المشكلات المذكورة أعلاه. لا توحي قراراتهم المستمرة المضمنة في Xcode و Swift Package Manager بأنهم سيفعلون ذلك. بمجرد أن تسمح بالتهيئة الضمنية كحالة صالحة، من الصعب الانتقال من هناك دون إدخال تغييرات معطلة. قد تؤدي العودة إلى المبادئ الأولى وإعادة التفكير في تصميم الأدوات إلى كسر العديد من مشاريع Xcode التي تم تجميعها عن طريق الخطأ لسنوات. تخيل ضجة المجتمع إذا حدث ذلك.
تجد آبل نفسها في مشكلة بين الدجاجة والبيضة. فالراحة هي ما يساعد المطورين على البدء بسرعة وإنشاء المزيد من التطبيقات لنظامها البيئي. لكن قراراتهم لجعل التجربة مريحة على هذا النطاق، يجعل من الصعب عليهم ضمان عمل بعض ميزات Xcode بشكل موثوق.
لأن المستقبل غير معروف، نحاول أن نكون قريبين قدر الإمكان من معايير الصناعة ومشاريع Xcode. نمنع المشاكل المذكورة أعلاه، ونستفيد من المعرفة التي لدينا لتوفير تجربة أفضل للمطورين. من الناحية المثالية لن نضطر إلى اللجوء إلى توليد المشاريع من أجل ذلك، ولكن عدم قابلية التوسعة في Xcode ومدير حزم Swift يجعل منه الخيار الوحيد القابل للتطبيق. وهو أيضًا خيار آمن لأنهم سيضطرون إلى كسر مشاريع Xcode لكسر مشاريع سويفت.
من الناحية المثالية، كان نظام البناء أكثر قابلية للتوسعة ، ولكن ألن يكون من السيئ أن يكون لدينا إضافات/ملحقات تتعاقد مع عالم من الضمنيات؟ لا تبدو فكرة جيدة. لذا يبدو أننا سنحتاج إلى أدوات خارجية مثل Tuist أو [Bazel] (https://bazel.build) لتوفير تجربة أفضل للمطورين. أو ربما ستفاجئنا آبل جميعًا وتجعل Xcode أكثر قابلية للتوسيع والصراحة...
إلى أن يحدث ذلك، عليك أن تختار ما إذا كنت تريد أن تتبنى راحة Xcode وتتحمل الديون التي تأتي معها، أو أن تثق بنا في هذه الرحلة لتقديم تجربة أفضل للمطورين. لن نخيب ظنك.
