قبل البدء في تنفيذ ميزة جديدة ، عليك كسر رأسك إلى حد ما.
يتطلب تطوير الوظائف المعقدة تنسيقًا جيدًا لجهود فريق من المهندسين.
واحدة من أهم النقاط هي مسألة موازاة المهام.
هل من الممكن إنقاذ جنود الخط الأمامي من الاضطرار إلى انتظار التنفيذ الخلفي؟ هل هناك طريقة لموازاة تطور الأجزاء الفردية من واجهة المستخدم؟
سيتم مناقشة موضوع موازنة المهام في تطوير الويب في هذه المقالة.

المشكلة
لذلك ، لنبدأ بتحديد المشكلة. تخيل أن لديك منتجًا متمرسًا (خدمة الإنترنت) ، حيث يتم جمع عدد قليل من الخدمات المختلفة. كل microservice في نظامك هو نوع من التطبيقات المصغرة المدمجة في البنية العامة وحل بعض المشكلات المحددة لمستخدم الخدمة. تخيل أنه صباح هذا اليوم (آخر يوم من سباق العدو) ، دعا مالك المنتج فاسيلي إلى مخاطبتك وأعلن: "في السباق التالي ، نبدأ في متابعة" استيراد البيانات "، مما سيجعل مستخدمي الخدمة أكثر سعادة. سيسمح للمستخدم بملء الخدمة على الفور من خلال مجموعة من مواقع dofigallard من 1C كثيفة! ".
تخيل أنك مدير أو قائد فريق ولا تستمع إلى كل هذه الأوصاف المتحمسة للمستخدمين السعداء من منظور العمل. يمكنك تقدير مقدار العمل الذي سيتطلبه كل هذا. بصفتك مديرًا جيدًا ، تبذل قصارى جهدك لتقليل شهية Vasily لتسجيل المهام في MVP (يشار إليها فيما يلي باسم "الحد الأدنى من المنتج القابل للتطبيق"). في الوقت نفسه ، لا يمكن استبعاد المطلبين الأساسيين لـ MVP - قدرة نظام الاستيراد على تحمل عبء كبير والعمل في الخلفية.
أنت تدرك أن الطريقة التقليدية ، عندما تتم معالجة جميع البيانات ضمن طلب المستخدم نفسه ، لن تعمل. هنا لديك لسياج الحديقة من أي عمال الخلفية. سيتعين عليك ربط "حافلة الأحداث" والتفكير في كيفية عمل موازن التحميل وقاعدة البيانات الموزعة وما إلى ذلك. بشكل عام ، كل المسرات العمارة microservice. نتيجة لذلك ، أنت تستنتج أن تطوير الواجهة الخلفية لهذه الميزة سيستمر ، لا تذهب إلى أصحاب الحظ.
السؤال الذي يطرح نفسه تلقائيًا: "ما الذي سيفعله جنود الخط الأمامي طوال هذا الوقت بينما لا توجد واجهة برمجة تطبيقات؟".
بالإضافة إلى ذلك ، اتضح أنه لا يجب استيراد البيانات على الفور. يجب عليك أولاً التحقق من صحتها والسماح للمستخدم بتصحيح جميع الأخطاء التي تم العثور عليها. اتضح سير العمل الماكرة على الواجهة الأمامية أيضا. ومن الضروري أن يحطم الميزة ، كالعادة ، "أمس". وبالتالي ، يجب تنسيق قدامى المحاربين في الحرب بطريقة أو بأخرى حتى لا يتصارعوا في اللفت ، ولا يخلقوا صراعات ويرون بهدوء كل جزء منها (انظر KDPV في بداية المقال).
في موقف مختلف ، يمكن أن نبدأ النشر من الخلف إلى الأمام. أولاً ، قم بتطبيق الواجهة الخلفية وتحقق من ثبات الحمل ، ثم قم بتعليق الواجهة الأمامية عليه بهدوء. ولكن المشكلة هي أن المواصفات تصف الميزة الجديدة بشكل عام ، ولها فجوات ونقاط مثيرة للجدل من حيث قابليتها للاستخدام. ولكن ماذا لو تبين في نهاية التطبيق الأمامي أن الميزة في هذا النموذج لن ترضي المستخدم؟ قد تتطلب تغييرات قابلية الاستخدام إجراء تغييرات على نموذج البيانات. سيتعين علينا إعادة كل من الأمام والخلف ، والتي ستكون مكلفة للغاية.
رشيقة تحاول مساعدتنا.

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

في وضعنا ، من الأفضل استخدام نهج مختلف. من الأفضل البدء فورًا في إنشاء واجهة (أمامية) للتأكد من صحة الفكرة الأولية لـ MVP. فمن ناحية ، يبدو أن واجهة المزخرفة لمالك المنتج فاسيلي ، والتي لا يوجد شيء وراءها ، تبدو وكأنها خدعة. من ناحية أخرى ، نحصل على ردود الفعل بسرعة كبيرة بهذه الطريقة عن جزء من الوظيفة التي سيواجهها المستخدم في المقام الأول. قد يكون لديك بنية رائعة بشكل لا يصدق ، ولكن إذا لم يكن هناك سهولة في الاستخدام ، فسيتم طرح التطبيق بالكامل على حافة التطبيق دون فهم التفاصيل. لذلك ، يبدو لي أكثر أهمية إعطاء واجهة المستخدم الأكثر وظيفية في أسرع وقت ممكن ، بدلاً من مزامنة تقدم المقدمة مع الواجهة الخلفية. لا فائدة من إصدار واجهة مستخدم غير مكتملة ودعم للاختبار ، لا تفي وظائفه بالمتطلبات الرئيسية. في الوقت نفسه ، قد يكون إصدار 80٪ من وظائف واجهة المستخدم المطلوبة ، ولكن دون وجود خلفية خلفية ، أمرًا مربحًا.
بعض التفاصيل الفنية
لذلك ، سبق أن وصفت بإيجاز الميزة التي سننفذها. أضف بعض التفاصيل الفنية.
يجب أن يكون المستخدم قادرًا على تحميل ملف بيانات كبير إلى الخدمة. يجب أن تكون محتويات هذا الملف بتنسيق محدد (على سبيل المثال ، CSV). يجب أن يحتوي الملف على بنية بيانات معينة وهناك حقول مطلوبة يجب ألا تكون فارغة. بمعنى آخر ، بعد التفريغ في الخلفية ، ستحتاج إلى التحقق من صحة البيانات. يمكن أن تستمر عملية التحقق من الصحة لفترة طويلة. لا يمكنك الاحتفاظ بالاتصال بالواجهة الخلفية مفتوحة (سوف تسقط عند انتهاء المهلة). لذلك ، يجب علينا قبول الملف بسرعة وبدء معالجة الخلفية. في نهاية عملية التحقق من الصحة ، يجب أن نبلغ المستخدم أنه يمكن أن يبدأ في تحرير البيانات. يجب على المستخدم تصحيح الأخطاء التي تم اكتشافها أثناء التحقق من الصحة.
بعد إصلاح جميع الأخطاء ، ينقر المستخدم على زر الاستيراد. يتم إرسال البيانات الصحيحة إلى الواجهة الخلفية. لإكمال إجراءات الاستيراد. يجب أن نبلغ الجهة الأمامية بالتقدم المحرز في جميع مراحل الاستيراد.
الطريقة الأكثر فعالية للتنبيه هي WebSockets. من المقدمة ، من خلال Websocket مع فترة معينة ، سيتم إرسال الطلبات للحصول على الوضع الحالي لمعالجة بيانات الخلفية. لمعالجة بيانات الخلفية ، نحتاج إلى معالجات خلفية ، وقائمة انتظار موزعة ، و Event Bus ، إلخ.
ينظر إلى تدفق البيانات على النحو التالي (كمرجع):
- من خلال واجهة برمجة تطبيقات متصفح الملفات ، نطلب من المستخدم تحديد الملف المطلوب من القرص.
- من خلال أجاكس نرسل الملف إلى الواجهة الخلفية.
- نحن في انتظار التحقق من صحة وتحليل ملف البيانات (نستقصي حالة تشغيل الخلفية عبر Websocket).
- عند الانتهاء من التحقق من الصحة ، سنقوم بتحميل البيانات المعدة للاستيراد وتقديمها في الجدول في صفحة الاستيراد.
- يقوم المستخدم بتحرير البيانات وتصحيح الأخطاء. بالنقر على الزر الموجود في أسفل الصفحة ، نرسل البيانات المصححة إلى الواجهة الخلفية.
- مرة أخرى على جانب العميل ، نقوم بإجراء استطلاع دوري لحالة تشغيل الخلفية.
- حتى نهاية الاستيراد الحالي ، يجب ألا يكون المستخدم قادرًا على بدء عملية استيراد جديدة (حتى في نافذة المتصفح المجاورة أو على الكمبيوتر المجاور).
خطة التنمية
Mocap UI vs. نموذج واجهة المستخدم

دعونا على الفور تسليط الضوء على الفرق بين Wireframe ، Mockup ، النموذج الأولي.
الصورة أعلاه تظهر السلكي. هذا مجرد رسم (بالأرقام أو على الورق - لا يهم). المفهومان الآخران أكثر تعقيدًا.
Mocap هو شكل من أشكال العرض التقديمي للواجهة المستقبلية التي يتم استخدامها فقط كعرض تقديمي وسيتم استبداله لاحقًا بالكامل. سيتم أرشفة هذا النموذج كعينة في المستقبل. سيتم تنفيذ الواجهة الحقيقية باستخدام أدوات أخرى. يمكن إجراء mocap في محرر متجه بتفاصيل تصميم كافية ، ولكن بعد ذلك سيضع مطورو الواجهة الأمامية جانبًا وينبذوا به كنموذج. يمكن صنع Mocap حتى في أجهزة إنشاء المستعرض المتخصصة ويأتي مع تفاعل محدود. لكن مصيره لم يتغير. سيصبح نموذجًا في ألبوم دليل التصميم.
يتم إنشاء النموذج الأولي باستخدام نفس الأدوات مثل واجهة المستخدم المستقبلية (على سبيل المثال ، React). تتم استضافة رمز النموذج الأولي في مستودع التطبيق العام. لن يتم استبداله ، كما هو الحال مع mocap. أولاً ، يتم استخدامه لاختبار المفهوم (Proof of Concept، PoC). بعد ذلك ، إذا نجح في الاختبار ، فسوف يبدأون في تطويره ، ويحولونه تدريجيًا إلى واجهة مستخدم كاملة.
الآن أقرب إلى النقطة ...
تخيل أن الزملاء من ورشة التصميم قدّموا لنا بعض التحف الفنية عن عمليتهم الإبداعية: نماذج من واجهة المستقبل. تتمثل مهمتنا في تخطيط العمل حتى يتسنى في أسرع وقت ممكن جعل العمل المتوازي للمحاربين القدماء ممكنًا.
نظرًا لأن تجميع الخوارزمية يبدأ برسم انسيابي ، نبدأ في إنشاء نموذج أولي باستخدام إطار سلكي بسيط (انظر الشكل أعلاه). على هذا Wireframe ، نقسم وظائف المستقبل إلى كتل كبيرة. المبدأ الرئيسي هنا هو تركيز المسؤولية. يجب ألا تقسم وظيفة واحدة إلى كتل مختلفة. الذباب يذهب إلى كتلة واحدة ، وشرحات إلى أخرى.
بعد ذلك ، تحتاج إلى إنشاء صفحة فارغة (دمية) في أقرب وقت ممكن ، وتكوين التوجيه ووضع رابط لهذه الصفحة في القائمة. ثم تحتاج إلى إنشاء فراغات للمكونات الأساسية (واحدة لكل كتلة في النموذج الأولي Wireframe). ولتغذية هذا الإطار الغريب في فرع تطوير ميزة جديدة.
نحصل على التسلسل الهرمي التالي للفروع في بوابة:
master ---------------------- > └ feature/import-dev ------ >
سيؤدي فرع "import-dev" دور عملية التنمية المتأخرة للميزة بأكملها. يُنصح بإصلاح شخص واحد مسؤول (مشرف) في هذا الفرع يقوم بإجراء تغييرات ذرية من جميع الزملاء العاملين على الميزة بالتوازي. يُنصح أيضًا بعدم الالتزام المباشر بهذا الفرع من أجل تقليل فرصة حدوث تعارضات وتغييرات غير متوقعة عندما تكون هناك عمليات اندماج في هذا الفرع من طلبات السحب الذرية.
لأن في هذه اللحظة ، قمنا بالفعل بإنشاء مكونات للكتل الرئيسية على الصفحة ، ثم يمكنك على الفور إنشاء فروع منفصلة لكل كتلة واجهة مستخدم. قد يبدو التسلسل الهرمي النهائي كما يلي:
master ----------------------- > └ feature/import-dev ------- > ├ feature/import-head ---- > ├ feature/import-filter -- > ├ feature/import-table --- > ├ feature/import-pager --- > └ feature/import-footer -- >
ملاحظة: لا يهم عند أي نقطة إنشاء هذه الحنفيات الذرية ، وأصطلاح التسمية المذكور أعلاه ليس الوحيد المناسب. برنش يمكن أن تنشأ مباشرة قبل بدء العمل. ويجب أن تكون أسماء البرنش واضحة لجميع المشاركين في التطوير. يجب أن يكون الاسم قصيرًا قدر الإمكان وأن يشير صراحةً إلى أي جزء من الوظيفة يكون الفرع مسؤولاً عنها.
من خلال النهج الموصوف أعلاه ، نحن نضمن التشغيل الخالي من الصراع للعديد من مطوري واجهة المستخدم. كل جزء واجهة مستخدم لديه دليل خاص به في التسلسل الهرمي للمشروع. يحتوي كتالوج الأجزاء على المكون الرئيسي ومجموعة الأنماط الخاصة به ومجموعة المكونات الفرعية الخاصة به. يمكن أن يكون لكل جزء أيضًا مدير حالة خاص به (حفلات MobX و Redux و VueX). ربما تستخدم مكونات الجزء بعض الأنماط العامة. ومع ذلك ، فإن تغيير الأنماط العامة عند تطوير جزء من صفحة جديدة محظور. تغيير السلوك الافتراضي وأسلوب الذرة العامة للتصميم أيضًا لا يستحق كل هذا العناء.
ملاحظة: "ذرة التصميم" تعني عنصرًا من مجموعة المكونات القياسية لخدمتنا - انظر التصميم الذري ؛ في حالتنا ، من المفترض أن نظام التصميم الذري قد تم تنفيذه بالفعل.
لذلك ، قمنا فعلياً بفصل جنود الخط الأمامي عن بعضهم البعض. الآن يمكن لكل منهم العمل بهدوء ، دون خوف من النزاعات مع الاندماج. أيضًا ، يمكن لأي شخص في أي وقت إنشاء طلب سحب من فرعه في ميزة / import-dev . بالفعل ، من الممكن الآن رمي المحتوى الثابت بهدوء وحتى تشكيل تفاعلي داخل وحدة تخزين واحدة.
ولكن كيف يمكننا ضمان أن شظايا واجهة المستخدم يمكن أن تتفاعل مع بعضها البعض؟
نحن بحاجة إلى تنفيذ الرابط بين الشظايا. خدمة JS ، التي تعمل كبوابة لتبادل البيانات مع النسخ الاحتياطي ، مناسبة لدور الارتباط بين الأجزاء. من خلال نفس الخدمة ، يمكنك تنفيذ إخطار الأحداث. من خلال الاشتراك في بعض الأحداث ، ستشمل الأجزاء ضمنًا دورة الحياة الكلية للجهاز المصغر. التغييرات في البيانات في جزء ما ستجعل من الضروري تحديث حالة جزء آخر. وبعبارة أخرى ، قمنا بتكامل الأجزاء من خلال البيانات ونموذج الحدث.
لإنشاء هذه الخدمة ، نحتاج إلى فرع آخر في بوابة:
master --------------------------- > └ feature/import-dev ----------- > ├ feature/import-js-service -- > ├ feature/import-head -------- > ├ feature/import-filter ------ > ├ feature/import-table ------- > ├ feature/import-pager ------- > └ feature/import-footer ------ >
ملاحظة: لا تخف من عدد الفروع ولا تتردد في إنتاج الفروع. Git يسمح لك بالعمل بكفاءة مع عدد كبير من الفروع. عندما تتطور العادة ، يصبح من السهل التفرع:
$/> git checkout -b feature/import-service $/> git commit . $/> git push origin HEAD $/> git checkout feature/import-dev $/> git merge feature/import-service
سوف يبدو هذا متوتراً بالنسبة للبعض ، ولكن الربح من تقليل النزاعات هو أكثر أهمية. بالإضافة إلى ذلك ، بينما أنت المالك الحصري للفرع ، يمكنك الدفع بأمان دون المخاطرة بإلحاق الضرر بالتاريخ المحلي لالتزامات شخص ما.
البيانات المزيفة
لذلك ، في المرحلة السابقة ، قمنا بإعداد خدمة JS للتكامل (importService) ، وقمنا بإعداد أجزاء UI. لكن بدون بيانات ، لن يعمل النموذج الأولي الخاص بنا. لا يتم رسم أي شيء باستثناء الزخارف الساكنة.
نحتاج الآن إلى اتخاذ قرار بشأن نموذج تقريبي للبيانات وإنشاء هذه البيانات في شكل ملفات JSON أو JS (يعتمد الخيار لصالح أحدهما أو الآخر على إعدادات الاستيراد في مشروعك ؛ يتم تكوين json-loader). تقوم importService لدينا ، وكذلك اختباراتها (سنفكر فيها لاحقًا) ، باستيراد البيانات اللازمة من هذه الملفات لمحاكاة الاستجابات من خلفية حقيقية (لم يتم تنفيذها بعد). حيث لوضع هذه البيانات ليست مهمة. الشيء الرئيسي هو أنه يمكن استيرادها بسهولة إلى importService نفسها واختبارات في microservice لدينا.
من المستحسن مناقشة تنسيق البيانات ، اتفاقية تسمية المجال مع مطوري الظهر على الفور. يمكنك ، على سبيل المثال ، الموافقة على استخدام تنسيق يتوافق مع مواصفات OpenAPI . أيا كان ما تتبعه مواصفات تنسيق النسخ ، فنحن ننشئ بيانات مزيفة وفقًا تمامًا لتنسيق بيانات النسخ.
ملاحظة: لا تخف من ارتكاب خطأ في نموذج البيانات المزيف ؛ مهمتك هي عمل مسودة نسخة من عقد البيانات ، والتي ستظل متفق عليها مع مطوري الواجهة الخلفية.
عقود
يمكن أن تكون البيانات المزيفة بداية جيدة للبدء في العمل على تحديد مواصفات واجهة برمجة التطبيقات المستقبلية في النهاية الخلفية. وهنا لا يهم من وكيف الجودة العالية تنفذ مشروع النموذج. حاسمة هو مناقشة مشتركة والتنسيق مع مشاركة المطورين الأمامي والخلفي.
يمكنك استخدام أدوات متخصصة لوصف العقود (مواصفات API). على سبيل المثال OpenAPI / Swagger . بطريقة جيدة ، عند وصف واجهة برمجة التطبيقات (API) باستخدام هذه الأداة ، ليست هناك حاجة لوجود جميع المطورين. يمكن القيام بذلك بواسطة مطور واحد (محرر المواصفات). كانت نتيجة مناقشة جماعية لواجهة برمجة التطبيقات الجديدة هي أن تكون بعض القطع الأثرية مثل MFU (اجتماع متابعة) ، والتي وفقًا لها يقوم محرر المواصفات أيضًا بإنشاء مرجع لواجهة برمجة التطبيقات المستقبلية.
في نهاية مواصفات المسودة ، لا ينبغي أن يستغرق الأمر وقتًا طويلاً للتحقق من الصحة. سيتمكن كل مشارك في المناقشة الجماعية ، بشكل مستقل عن الآخرين ، من إجراء فحص سريع للتحقق من أن رأيه قد تم أخذه في الاعتبار. إذا بدا شيء غير صحيح ، فسيكون من الممكن توضيح مواصفات المحرر (اتصالات العمل العادية). إذا كان الجميع راضيًا عن المواصفات ، فيمكن نشرها واستخدامها كوثائق للخدمة.
اختبار وحدة
ملاحظة: بالنسبة لي ، قيمة اختبارات الوحدة منخفضة جدًا. أنا هنا أتفق مع David Heinemeier Hansson @ RailsConf . "تعد اختبارات الوحدات طريقة رائعة للتأكد من أن برنامجك يقوم بما يمكنك القيام به ... كما هو متوقع." لكنني أعترف بحالات خاصة عندما تجلب اختبارات الوحدة الكثير من الفوائد.
الآن وقد قررنا البيانات المزيفة ، يمكننا البدء في اختبار الوظيفة الأساسية. لاختبار المكونات الأمامية ، يمكنك استخدام أدوات مثل الكرمة ، jest ، mocha ، chai ، الياسمين. عادةً ما يتم وضع الملف الذي يحمل نفس الاسم مع postfix "spec" أو "test" بجوار مورد JS قيد الاختبار:
importService ├ importService.js └ importService.test.js
تعتمد القيمة المحددة لل postfix على إعدادات أداة تجميع حزم JS في مشروعك.
بالطبع ، في الحالة التي يكون فيها الظهر في حالة "منع الحمل" ، يكون من الصعب للغاية تغطية جميع الحالات الممكنة باختبارات وحدة. لكن الغرض من اختبارات الوحدة مختلف قليلاً. وهي مصممة لاختبار تشغيل القطع الفردية من المنطق.
على سبيل المثال ، من الجيد تغطية أنواع مختلفة من المساعدين من خلال اختبارات الوحدة ، والتي من خلالها تتم مشاركة أجزاء من المنطق أو خوارزميات معينة بين مكونات وخدمات JS. أيضًا ، يمكن أن تغطي هذه الاختبارات السلوك في مكونات ومخازن MobX و Redux و VueX استجابة لتغيرات بيانات المستخدم.
التكامل واختبار E2E
اختبارات التكامل تعني التحقق من سلوك النظام للتأكد من توافقه مع المواصفات. أي تم التحقق من أن المستخدم سيرى بالضبط السلوك الموضح في المواصفات. هذا هو مستوى أعلى من الاختبار مقارنة مع اختبارات الوحدة.
على سبيل المثال ، اختبار يتحقق من وجود خطأ أسفل الحقل المطلوب عندما يقوم المستخدم بمسح النص بالكامل. أو اختبار يتحقق من وجود خطأ أثناء محاولة حفظ بيانات غير صالحة.
تعمل اختبارات E2E (النهاية إلى النهاية) على مستوى أعلى. يتحققون من أن سلوك واجهة المستخدم صحيح. على سبيل المثال ، التحقق من أنه بعد إرسال ملف البيانات إلى الخدمة ، يظهر للمستخدم تحريفًا يشير إلى استمرار عملية غير متزامنة. أو تحقق من أن تصور المكونات القياسية للخدمة يتوافق مع أدلة المصممين.
يعمل هذا النوع من الاختبار مع بعض إطار أتمتة واجهة المستخدم. على سبيل المثال ، يمكن أن يكون السيلينيوم . يتم تشغيل مثل هذه الاختبارات مع Selenium WebDriver في بعض المستعرضات (عادةً Chrome مع "وضع مقطوع الرأس"). إنهم يعملون لفترة طويلة ، لكنهم يخففون العبء عن أخصائيي ضمان الجودة ، ويقومون بإجراء اختبار دخان لهم.
كتابة هذه الأنواع من الاختبارات تستغرق وقتًا طويلاً. كلما أسرعنا في كتابتها ، كان ذلك أفضل. على الرغم من حقيقة أنه ليس لدينا نسخة احتياطية كاملة ، يمكننا بالفعل البدء في وصف اختبارات التكامل. لدينا بالفعل المواصفات.
مع وصف E2E ، فإن اختبار العائق أقل. لقد قمنا بالفعل برسم المكونات القياسية من مكتبة ذرات التصميم. نفذت أجزاء محددة من واجهة المستخدم. جعل بعض التفاعلية على رأس البيانات وهمية و API في importService. لا شيء يمنعك من بدء تشغيل أتمتة واجهة المستخدم ، على الأقل للحالات الأساسية.
من خلال كتابة هذه الاختبارات ، يمكنك أن تحير مرة أخرى المطورين الفرديين إذا لم يكن هناك أشخاص محيرون. وأيضًا لوصف الاختبارات ، يمكنك إنشاء فرع منفصل (كما هو موضح أعلاه). في الفروع للاختبارات ، سيكون من الضروري تحديث التحديثات بشكل دوري من الفرع " feature / import-dev ".
سيكون التسلسل العام لعمليات الدمج كما يلي:
- على سبيل المثال ، أنشأ مطور من فرع " Feature / import-filter " فرعًا للعلاقات العامة. تتم معاينة هذه العلاقات العامة ويقوم المشرف على فرع " Feature / import-dev " بحقن هذا PR.
- Maintainer تعلن عن سكب التحديث.
- يقوم المطور في الفرع " feature / import-tests-e2e " بسحب التغييرات المتطرفة مع الدمج من فرع "-dev".
CI واختبار التشغيل الآلي
يتم تنفيذ اختبارات الواجهة الأمامية باستخدام الأدوات التي تعمل من خلال CLI. في package.json ، تتم كتابة الأوامر لتشغيل أنواع مختلفة من الاختبارات. لا يتم استخدام هذه الأوامر فقط من قبل المطورين في البيئة المحلية. هناك حاجة أيضًا لإجراء الاختبارات في بيئة CI (التكامل المستمر).
إذا قمنا الآن بتشغيل البنية في CI ولم تكن هناك أخطاء ، فسيتم تسليم النموذج الأولي الذي طال انتظاره إلى بيئة الاختبار (80٪ من الوظائف في المقدمة مع خلفية خلفية لم يتم تنفيذها بعد). يمكننا أن نظهر فاسيلي السلوك التقريبي لل microservice في المستقبل. ركل فاسيلي هذا النموذج الأولي ، وربما يدلي ببعض الملاحظات (ربما حتى تلك الخطيرة). في هذه المرحلة ، إجراء التعديلات غير مكلف. في حالتنا ، يتطلب الدعم تغييرات معمارية خطيرة ، لذلك يمكن أن يكون العمل عليه أبطأ من الأمام. طالما لم يتم الانتهاء من الدعم ، فإن التغييرات في خطة تطويرها لن تؤدي إلى عواقب وخيمة. إذا لزم الأمر ، قم بتغيير شيء ما في هذه المرحلة ، فسنطلب منك إجراء تعديلات على مواصفات واجهة برمجة التطبيقات (في swagger). بعد ذلك ، يتم تكرار الخطوات الموضحة أعلاه. لا يزال العاملون في الخطوط الأمامية لا يعتمدون على العوامل الخلفية. متخصصون الواجهة الأمامية الفردية مستقلة عن بعضها البعض.
الواجهة الخلفية. تحكم كعب
نقطة الانطلاق لتطوير واجهة برمجة التطبيقات في النهاية الخلفية هي مواصفات واجهة برمجة التطبيقات المعتمدة ( OpenAPI / Swagger ). إذا كانت هناك مواصفات ، فسيصبح دعم التوازي أسهل أيضًا. يجب أن يؤدي تحليل المواصفات إلى دفع المطورين إلى التفكير في العناصر الأساسية للبنية. ما المكونات / الخدمات الشائعة التي تحتاج إلى إنشائها قبل متابعة تنفيذ مكالمات API الفردية. وهنا مرة أخرى ، يمكنك تطبيق النهج كما هو الحال مع الفراغات لواجهة المستخدم.
يمكننا أن نبدأ من الأعلى ، أي من الطبقة الخارجية لظهرنا (من وحدات التحكم). في هذه المرحلة ، نبدأ بالتوجيه وفراغات التحكم والبيانات المزيفة. طبقة الخدمات (BL) والوصول إلى البيانات (DAL) الذي لم نفعله بعد. نحن ببساطة نقل البيانات من JS إلى الواجهة الخلفية وبرمجة وحدات التحكم بحيث تنفذ الإجابات المتوقعة للحالات الأساسية ، وإعطاء قطع من البيانات المزيفة.
عند الانتهاء من هذه المرحلة ، يجب على جنود الخطوط الأمامية الحصول على خلفية عمل على بيانات الاختبار الثابتة. علاوة على ذلك ، إنها بالضبط البيانات التي يكتب عليها جنود الخط الأمامي اختبارات الاندماج. من حيث المبدأ ، في هذه اللحظة ، لن يكون من الصعب تبديل بوابة JS (importService) لاستخدام فراغات التحكم في الخلف.
من الناحية النظرية ، لا يختلف جزء الاستجابة للطلبات من خلال Websocket عن وحدات تحكم Web API. نحن أيضًا نجعل هذه "الإجابة" على بيانات الاختبار ونربط importService بهذا الإعداد.
في النهاية ، يجب نقل جميع JS للعمل مع خادم حقيقي.
الواجهة الخلفية. الانتهاء من وحدات التحكم. بذرة DAO
حان الآن دور الانتهاء من طبقة الدعم الخارجية. بالنسبة لوحدات التحكم ، يتم تنفيذ الخدمات واحدة تلو الأخرى في BL. الآن سوف تعمل الخدمات مع البيانات المزيفة. الإضافة في هذه المرحلة هي أننا في الخدمات نطبق بالفعل منطق عمل حقيقي. في هذه المرحلة ، يُنصح ببدء إضافة اختبارات جديدة وفقًا لمنطق مواصفات العمل. من المهم عدم سقوط اختبار التكامل.
ملاحظة: ما زلنا لا نعتمد على ما إذا كان مخطط البيانات قد تم تطبيقه في قاعدة البيانات.
الواجهة الخلفية. وضع اللمسات الأخيرة على DAO. ديسيبل الحقيقي
بعد تنفيذ مخطط البيانات في قاعدة البيانات ، يمكننا نقل بيانات الاختبار من الخطوات السابقة إليها وتبديل DAL البدائي الخاص بنا للعمل مع خادم قاعدة البيانات الحقيقي. لأن نقوم بنقل البيانات الأولية التي تم إنشاؤها للجبهة إلى قاعدة البيانات ، يجب أن تظل جميع الاختبارات ذات صلة. إذا سقط أي من الاختبارات ، فسيحدث خطأ ما وتحتاج إلى فهمه.
ملاحظة: بشكل عام ، مع وجود احتمالية عالية جدًا للعمل مع نظام البيانات في قاعدة البيانات ، سيكون هناك القليل لميزة جديدة ؛ ربما سيتم إجراء تغييرات على قاعدة البيانات في وقت واحد مع تنفيذ الخدمات في BL.
في نهاية هذه المرحلة ، حصلنا على خدمة microservice كاملة ، إصدار ألفا. يمكن بالفعل عرض هذا الإصدار للمستخدمين الداخليين (مالك المنتج أو تقني المنتج أو أي شخص آخر) للتقييم باعتباره MVP.
ستستمر عمليات التكرار القياسية من Agile للعمل على إصلاح الأخطاء وتنفيذ الرقائق الإضافية والتلميع النهائي.
استنتاج
أعتقد أنك يجب أن لا تستخدم ما سبق عمياء كدليل للعمل. تحتاج أولاً إلى تجربة مشروعك والتكيف معه. الأسلوب الموضح أعلاه قادر على فك المطورين الفرديين من بعضهم البعض والسماح لهم بالعمل بالتوازي في ظل ظروف معينة. مع كل الإيماءات مع نقل البيانات ونقل البيانات ، فإن تنفيذ الفراغات على البيانات المزيفة يبدو وكأنه حمل كبير. يظهر الربح في هذا الحمل بسبب زيادة التزامن. إذا كان فريق التطوير يتكون حفار واحد ونصف كدسات كاملة أو freotovik واحد مع خلفية واحدة ، ثم سيكون هناك ربما الكثير من الربح من هذا النهج. على الرغم من أنه في هذه الحالة ، قد تزيد بعض النقاط من فعالية التنمية.
يظهر الربح من هذا النهج عندما ننفذ بسرعة في البداية قطع العمل القريبة قدر الإمكان من التنفيذ الحقيقي المستقبلي ونفصل ماديًا عن العمل على أجزاء مختلفة على مستوى بنية الملف في المشروع وعلى مستوى نظام إدارة الشفرة (git).
آمل أن تكونوا قد وجدت هذه المادة مفيدة.
شكرا لاهتمامكم!