كيفية فصل الواجهة الأمامية والخلفية مع الحفاظ على التفاهم المتبادل

صورة


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


قبل بضع سنوات ، قرأت في مقال علمي أن هناك حاجة إلى المزيد من الوقت للتدريب الكامل ، وفي المستقبل القريب سيستغرق الأمر ثمانين عامًا لاكتساب المعرفة. على ما يبدو ، لقد حان هذا المستقبل بالفعل في مجال تكنولوجيا المعلومات.


كنت محظوظًا بما فيه الكفاية لبدء البرمجة في تلك السنوات عندما لم يكن هناك فصل بين المبرمجين في الواجهة الخلفية والمبرمجين في الواجهة الأمامية ، عندما لم تكن الكلمات "prototype" و "engineer product" و "UX" و "QA" سليمة. كان العالم أكثر بساطة ، وكانت الأشجار أطول وأكثر خضرة ، وكان الهواء أكثر نظافة ولعب الأطفال في الساحات بدلاً من مواقف السيارات. بغض النظر عن كيف أريد العودة في ذلك الوقت ، يجب أن أعترف أن كل هذا ليس هو نية الفقير ، ولكن التطور التطوري للمجتمع. نعم ، يمكن أن يتطور المجتمع بشكل مختلف ، ولكن ، كما تعلمون ، لا يتسامح التاريخ مع الحالة المزاجية.


قبل التاريخ


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


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


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


الواجهة الأمامية والخلفية


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


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


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


صورة
"سنبذل قصارى جهدنا في مشروع واحد ، سيكون أكثر ملاءمة" ، قالوا ...


هندسة معمارية


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


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


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


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


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


صورة
زيادة الاستقرار عن طريق تقسيم مجالات المسؤولية.


اتصالات


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


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


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


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


ربما لا يكون "API" هو أنسب اسم للفريق ، فإن شيئًا ما يتعلق بالهندسة المعمارية أو الرؤية واسعة النطاق سيكون أكثر ملاءمة ، لكن أعتقد أن هذا التافه لا يغير الجوهر.


API


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


برزت أهداف واجهة برمجة التطبيقات الجديدة من الصعوبات اليومية في تنفيذ أفكار المنتجات والتصميم الجديدة. نحن بحاجة:


  1. اتصال ضعيف لمكونات النظام بحيث يمكن تطوير الواجهة الخلفية والواجهة الأمامية بشكل متوازٍ.
  2. قابلية تطوير عالية بحيث لا تتداخل واجهة برمجة التطبيقات الجديدة مع وظائف المبنى.
  3. الاستقرار والاتساق.

لم يبدأ البحث عن حل لواجهة برمجة التطبيقات بالواجهة الخلفية ، كما هو مقبول عادة ، ولكن على العكس من ذلك ، فكر في ما يحتاجه المستخدمون.


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


حل مشترك آخر هو GraphQL. كما أنها ليست مثالية ، ولكن على عكس REST ، فإن واجهة برمجة تطبيقات GraphQL ليست مجرد نموذج وصفي ، لكنها قواعد حقيقية.


في وقت سابق ، تحدثت عن النظام ، الذي كان من المفترض أن ينسق عمل الواجهة الأمامية والخلفية. الطبقة البينية هي بالضبط المستوى المتوسط. بعد النظر في الخيارات الممكنة للعمل مع الخادم ، استقرنا على GraphQL كواجهة برمجة تطبيقات للواجهة الأمامية . ولكن ، بما أن الخلفية مكتوبة بلغة C ++ ، فإن تنفيذ خادم GraphQL تبين أنه ليس مهمة تافهة. لن أصف كل الصعوبات والحيل التي ذهبنا إليها من أجل التغلب عليها ، لم تحقق نتيجة حقيقية. نظرنا إلى المشكلة من الجانب الآخر وقررنا أن البساطة هي مفتاح النجاح. لذلك ، توصلنا إلى حلول مثبتة: خادم Node.js منفصل مع Express.js و Apollo Server.


بعد ذلك ، كان عليك تحديد كيفية الوصول إلى واجهة برمجة تطبيقات الواجهة الخلفية. في البداية نظرنا في اتجاه رفع واجهة برمجة تطبيقات REST ، ثم حاولنا استخدام الوظائف الإضافية في C ++ لـ Node.js. نتيجةً لذلك ، أدركنا أن كل هذا لا يناسبنا ، وبعد تحليل مفصل للواجهة الخلفية ، اخترنا واجهة برمجة تطبيقات تستند إلى خدمات gRPC .


بعد تجميع الخبرة المكتسبة في استخدام C ++ و TypeScript و GraphQL و gRPC ، حصلنا على بنية تطبيق تسمح بتطوير مرن للواجهة الخلفية والواجهة الأمامية ، مع الاستمرار في إنشاء منتج برمجي واحد.


والنتيجة هي مخطط حيث تتصل الواجهة الأمامية بخادم وسيط باستخدام استعلامات GraphQL (تعرف ما يجب طرحه وما سيحصل عليه في المقابل). يستدعي خادم graphQL في أدوات التحليل وظائف API لخادم gRPC ، ولهذا يستخدمون مخططات Protobuf للاتصال. يعرف خادم واجهة برمجة التطبيقات المستندة إلى gRPC أي خدمة من microservice لنقل البيانات منها أو إلى من يرسل الطلب. الخدمات الميكروية نفسها مبنية أيضًا على gRPC ، مما يضمن سرعة معالجة الاستعلام وكتابة البيانات والقدرة على استخدام لغات البرمجة المختلفة لتطويرها.


صورة
المخطط العام للعمل بعد التغيير في العمارة


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


يؤدي


لقد قطعنا الطريق التطوري لتطوير منتج وفريق. تحقق النجاح أو تحول المشروع إلى فشل ، وربما يكون من المبكر الحكم ، ولكن يمكن تلخيص النتائج الوسيطة. ما لدينا الآن:


  1. الواجهة الأمامية مسؤولة عن الشاشة ، والواجهة الخلفية مسؤولة عن البيانات.
  2. في النهاية الأمامية ، ظلت المرونة من حيث الاستعلام عن البيانات وتلقيها. تعرف الواجهة ما يمكنك طرحه على الخادم والإجابات التي يجب أن تكون.
  3. الواجهة الخلفية لديها الفرصة لتغيير التعليمات البرمجية مع الثقة في أن واجهة المستخدم ستواصل العمل. أصبح من الممكن التبديل إلى بنية microservice دون الحاجة إلى إعادة الواجهة الأمامية بالكامل.
  4. يمكنك الآن استخدام بيانات وهمية للواجهة الأمامية عندما لا تكون الواجهة الخلفية جاهزة بعد.
  5. أدى إنشاء مخططات التعاون إلى القضاء على مشكلات التفاعل عندما تفهم الفرق المهمة نفسها بشكل مختلف. تم تقليل عدد التكرارات لتغيير تنسيقات البيانات: نحن نعمل على مبدأ "القياس سبع مرات ، يتم قطع مرة واحدة".
  6. الآن يمكنك خطة العمل العدو بالتوازي.
  7. لتطبيق خدمات micros الفردية ، يمكنك الآن تعيين مطورين ليسوا على دراية بـ C ++.

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


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


لقد تطرقت هنا بشكل سطحي إلى مسائل فريق العمل الجماعي على منتج واحد ، واختيار تقنية واجهة برمجة التطبيقات (REST vs GraphQL) ، وربط تطبيقات Node.js مع C ++ ، وما إلى ذلك. يرسم كل موضوع من هذه الموضوعات مقالة منفصلة ، وإذا كنت مهتمًا ، سوف نكتب لهم.

Source: https://habr.com/ru/post/ar447650/


All Articles