البنية المعيارية (TMA)
TMA هو نهج معماري لهيكلة تطبيقات Apple OS لتمكين قابلية التوسع، وتحسين دورات الإنشاء والاختبار، وضمان الممارسات الجيدة في فريقك. وتتمثل فكرته الأساسية في بناء تطبيقاتك من خلال بناء ميزات مستقلة مترابطة باستخدام واجهات برمجة تطبيقات واضحة وموجزة.
تقدم هذه الإرشادات مبادئ البنية، مما يساعدك على تحديد وتنظيم ميزات تطبيقك في طبقات مختلفة. كما تقدم نصائح وأدوات ونصائح إذا قررت استخدام هذه البنية.
µمعلومات µمعلومات
كانت هذه البنية تُعرف سابقًا باسم µFeatures. لقد أعدنا تسميتها إلى البنية المعيارية (TMA) لتعكس بشكل أفضل الغرض منها والمبادئ الكامنة وراءها.
المبدأ الأساسي
يجب أن يكون المطورون قادرين على بناء واختبار وتجربة ميزاتهم بسرعة، بشكل مستقل عن التطبيق الرئيسي، مع ضمان عمل ميزات Xcode مثل معاينات واجهة المستخدم وإكمال التعليمات البرمجية وتصحيح الأخطاء بشكل موثوق.
ما هي الوحدة النمطية
تمثل الوحدة النمطية ميزة التطبيق وهي مزيج من الأهداف الخمسة التالية (حيث يشير الهدف إلى هدف Xcode):
- المصدر: يحتوي على شيفرة مصدر الميزة (Swift، Objective-C، C++، JavaScript...) ومواردها (الصور، الخطوط، القصص المصورة، xibs).
- الواجهة: هو هدف مصاحب يحتوي على الواجهة العامة ونماذج الميزة.
- الاختبارات: يحتوي على اختبارات وحدة الميزة واختبارات التكامل.
- الاختبار: يوفر بيانات الاختبار التي يمكن استخدامها في الاختبارات ومثال التطبيق. يوفر أيضًا نماذج لفئات الوحدات النمطية والبروتوكولات التي يمكن استخدامها من قبل ميزات أخرى كما سنرى لاحقًا.
- مثال: يحتوي على مثال على تطبيق يمكن للمطورين استخدامه لتجربة الميزة في ظل ظروف معينة (لغات مختلفة، أحجام الشاشة، الإعدادات).
نوصي باتباع اصطلاح التسمية للأهداف، وهو أمر يمكنك فرضه في مشروعك بفضل DSL الخاص بـ Tuist.
| الهدف | التبعيات | المحتوى |
|---|---|---|
الميزة | واجهة الميزة | شفرة المصدر والموارد |
واجهة الميزة | - | الواجهة العامة والنماذج |
اختبارات الميزات | الميزة ، اختبار الميزة اختبار الميزة | اختبارات الوحدة والتكامل |
اختبار الميزات | واجهة الميزة | اختبار البيانات والنماذج |
مثال على الميزة | ميزةالاختبار ، ميزة | مثال على التطبيق |
معاينات واجهة المستخدم
الميزة يمكن استخدام FeatureTesting كأصل تطوير للسماح بمعاينة واجهة المستخدم
تجميع التوجيهات بدلاً من اختبار الأهداف
بدلًا من ذلك، يمكنك استخدام توجيهات المحول البرمجي لتضمين بيانات الاختبار والنماذج في أهداف ميزة أو ميزة الواجهة عند التحويل البرمجي لـ Debug. يمكنك تبسيط الرسم البياني، ولكن سينتهي بك الأمر بتجميع شيفرة لن تحتاجها لتشغيل التطبيق.
لماذا وحدة نمطية
واجهات برمجة التطبيقات الواضحة والموجزة
عندما تعيش جميع التعليمات البرمجية المصدرية للتطبيق في نفس الهدف، فمن السهل جدًا بناء تبعيات ضمنية في التعليمات البرمجية وينتهي الأمر بتشفير السباغيتي المعروف. كل شيء مقترن بقوة، ولا يمكن التنبؤ بالحالة في بعض الأحيان، ويصبح إدخال تغييرات جديدة كابوسًا. عندما نحدد الميزات في أهداف مستقلة، نحتاج إلى تصميم واجهات برمجة التطبيقات العامة كجزء من تنفيذ ميزاتنا. نحتاج أن نقرر ما يجب أن يكون عامًا، وكيف يجب أن تُستهلَك ميزتنا، وما الذي يجب أن يبقى خاصًا. لدينا المزيد من التحكم في الطريقة التي نريد أن يستخدم بها عملاء ميزتنا الميزة ويمكننا فرض ممارسات جيدة من خلال تصميم واجهات برمجة تطبيقات آمنة.
الوحدات الصغيرة
[فرّق تسد] (https://en.wikipedia.org/wiki/Divide_and_conquer). يتيح لك العمل في وحدات صغيرة الحصول على مزيد من التركيز واختبار الميزة وتجربتها بمعزل عن غيرها. علاوة على ذلك، تكون دورات التطوير أسرع بكثير نظرًا لأن لدينا تجميعًا أكثر انتقائية، حيث نقوم بتجميع المكونات الضرورية فقط لتشغيل ميزتنا. تجميع التطبيق بأكمله ضروري فقط في نهاية عملنا، عندما نحتاج إلى دمج الميزة في التطبيق.
قابلية إعادة الاستخدام
يتم تشجيع إعادة استخدام التعليمات البرمجية عبر التطبيقات والمنتجات الأخرى مثل الإضافات باستخدام الأطر أو المكتبات. من خلال بناء الوحدات النمطية فإن إعادة استخدامها أمر بسيط للغاية. يمكننا بناء ملحق iMessage أو ملحق Today أو تطبيق watchOS بمجرد دمج الوحدات الموجودة وإضافة (عند الضرورة) طبقات واجهة المستخدم الخاصة بالمنصة .
التبعيات
عندما تعتمد وحدة نمطية على وحدة نمطية أخرى، فإنها تعلن تبعية ضد هدف واجهتها. فائدة ذلك ذات شقين. فهو يمنع اقتران تنفيذ وحدة نمطية ما بتنفيذ وحدة نمطية أخرى، كما أنه يسرع من عمليات الإنشاء النظيفة لأنه لا يتعين عليهم تجميع تنفيذ الميزة الخاصة بنا وواجهات التبعيات المباشرة والمتعدية. هذا النهج مستوحى من فكرة SwiftRock لـ [تقليل أوقات بناء نظام iOS باستخدام وحدات الواجهة] (https://swiftrocks.com/reducing-ios-build-times-by-using-interface-targets).
يتطلب الاعتماد على الواجهات أن تقوم التطبيقات ببناء الرسم البياني للتطبيقات في وقت التشغيل، وحقن التبعية في الوحدات التي تحتاج إليها. على الرغم من أن TMA غير معني بكيفية القيام بذلك، إلا أننا نوصي باستخدام حلول أو أنماط حقن التبعية أو الحلول التي لا تضيف عمليات حقن تبعية في وقت الإنشاء أو استخدام واجهات برمجة التطبيقات الخاصة بالمنصة التي لم يتم تصميمها لهذا الغرض.
أنواع المنتجات
عند إنشاء وحدة نمطية، يمكنك الاختيار بين المكتبات والأطر ، و الربط الثابت والديناميكي للأهداف. بدون تويست، يكون اتخاذ هذا القرار أكثر تعقيدًا بعض الشيء لأنك تحتاج إلى تكوين الرسم البياني للتبعية يدويًا. ومع ذلك، بفضل مشاريع تويست، لم تعد هذه مشكلة.
نوصي باستخدام مكتبات أو أطر عمل ديناميكية أثناء التطوير باستخدام
ملحقات الحزمة لفصل منطق الوصول إلى الحزمة عن طبيعة المكتبة أوإطار العمل للهدف. هذا أمر أساسي للحصول على أوقات تجميع سريعة ولضمان عمل [SwiftUI Previews] (https://developer.apple.com/documentation/swiftui/previews-in-xcode) بشكل موثوق. والمكتبات أو الأطر الثابتة لإصدارات الإصدارات لضمان تشغيل التطبيق بسرعة. يمكنك الاستفادة من
التكوين الديناميكي لتغيير نوع المنتج في وقت الإنشاء:bash
# You'll have to read the value of the variable from the manifest {#youll-have-to-read-the-value-of-the-variable-from-the-manifest}
# and use it to change the linking type {#and-use-it-to-change-the-linking-type}
TUIST_PRODUCT_TYPE=static-library tuist generateswift
// You can place this in your manifest files or helpers
// and use the returned value when instantiating targets.
func productType() -> Product {
if case let .string(productType) = Environment.productType {
return productType == "static-library" ? .staticLibrary : .framework
} else {
return .framework
}
}المكتبات القابلة للدمج
حاولت شركة Apple التخفيف من عبء التبديل بين المكتبات الثابتة والديناميكية من خلال تقديم [مكتبات قابلة للدمج] (https://developer.apple.com/documentation/xcode/configuring-your-project-to-use-mergeable-libraries). ومع ذلك، فإن ذلك يُدخل عدم تحديد وقت الإنشاء مما يجعل الإنشاء غير قابل للتكرار ويصعب تحسينه لذا لا ننصح باستخدامه.
الرمز
TMA غير معني ببنية الكود وأنماطه للوحدات النمطية الخاصة بك. ومع ذلك، نود مشاركة بعض النصائح بناءً على خبرتنا:
- الاستفادة من المحول البرمجي أمر رائع. قد ينتهي الأمر بالإفراط في الاستفادة من المحول البرمجي إلى أن يكون غير مثمر ويتسبب في عدم موثوقية عمل بعض ميزات Xcode مثل المعاينات. نوصي باستخدام المحول البرمجي لفرض الممارسات الجيدة واكتشاف الأخطاء مبكرًا، ولكن ليس إلى الحد الذي يجعل قراءة الشيفرة البرمجية وصيانتها أصعب.
- استخدم وحدات ماكرو سويفت باعتدال. قد تكون قوية جدًا ولكنها قد تجعل قراءة الشيفرة البرمجية وصيانتها أصعب.
- احتضن المنصة واللغة، ولا تجردهما. قد تؤدي محاولة ابتكار طبقات تجريدية متقنة إلى نتائج عكسية. المنصة واللغة قويتان بما يكفي لبناء تطبيقات رائعة دون الحاجة إلى طبقات تجريد إضافية. استخدم أنماط البرمجة والتصميم الجيدة كمرجع لبناء ميزاتك.
الموارد
- [بناء µميزات البناء] (https://speakerdeck.com/pepibumur/building-ufeatures)
- [البرمجة الموجهة نحو الإطار] (https://speakerdeck.com/pepibumur/framework-oriented-programming-mobilization-dot-pl)
- [رحلة في الأطر والسويفت] (https://speakerdeck.com/pepibumur/a-journey-into-frameworks-and-swift)
- [الاستفادة من أطر العمل لتسريع عملية التطوير على نظام iOS - الجزء 1] (https://developers.soundcloud.com/blog/leveraging-frameworks-to-speed-up-our-development-on-ios-part-1)
- [البرمجة الموجهة للمكتبة] (https://academy.realm.io/posts/justin-spahr-summers-library-oriented-programming/)
- [بناء أطر عمل حديثة] (https://developer.apple.com/videos/play/wwdc2014/416/)
- [الدليل غير الرسمي لملفات xcconfig] (https://pewpewthespells.com/blog/xcconfig_guide.html)
- المكتبات الثابتة والديناميكية
