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

في خريف هذا العام ، أصبح Yandex.Market يبلغ من العمر 18 عامًا. طوال هذا الوقت ، تم تطوير واجهة السوق التابعة. باختصار ، هذه هي لوحة الإدارة التي تستطيع المتاجر من خلالها تحميل الكتالوجات ، والعمل مع المجموعة ، ومراقبة الإحصائيات ، والرد على المراجعات ، وما إلى ذلك. تفاصيل المشروع هي أنه يجب عليك التفاعل كثيرًا مع مختلف الخلفيات. ومع ذلك ، لا يمكن دائمًا الحصول على البيانات في مكان واحد ، من خلفية واحدة محددة.
أعراض مشكلة
لذا ، تخيل ، كان هناك نوع من المشاكل. يذهب المدير مع المهمة للمصممين - يرسمون التخطيط. ثم يذهب إلى النهاية الخلفية - يقومون بعمل بعض
الأقلام ويكتبون قائمة بالمعلمات وتنسيق الاستجابة على الويكي الداخلي.
ثم يذهب المدير إلى الواجهة الأمامية بعبارة "لقد أحضرت لك واجهة برمجة التطبيقات" ويعرض النص البرمجي لكل شيء بسرعة ، لأنه ، في رأيه ، تم تنفيذ جميع الأعمال تقريبًا.
تنظر إلى الوثائق وترى هذا:
№ | ---------------------- 53 | feed_shoffed_id 54 | fesh 55 | filter-currency 56 | showVendors
لا تلاحظ أي شيء غريب؟ جمل وثعبان وحافظة كباب في قلم واحد. أنا لا أتحدث عن معلمة fesh. ما هو fesh على الإطلاق؟ مثل هذه الكلمة غير موجودة. حاول أن تخمن قبل أن تفتح المفسد.
المفسدFesh هو عامل تصفية حسب معرّف المتجر. يمكنك تمرير عدة معرفات مفصولة بفواصل. قد يسبق المعرّف بعلامة الطرح ، مما يعني أنه يجب استبعاد هذا المتجر من النتائج.
في الوقت نفسه ، من JavaSctipt ، بالطبع ، لا يمكنني الوصول إلى خصائص مثل هذا الكائن من خلال تدوين منقط. ناهيك عن حقيقة أنه إذا كان لديك أكثر من 50 معلمة في مكان واحد ، فمن الواضح أنك تحولت إلى مكان آخر في حياتك.
هناك الكثير من الخيارات لواجهة برمجة تطبيقات غير ملائمة. مثال كلاسيكي - تبحث واجهة برمجة التطبيقات وتعرض النتائج:
result: [ {id: 1, name: 'IPhone 8'}, {id: 2, name: 'IPhone 8 Plus'}, {id: 3, name: 'IPhone X'}, ] result: {id: 1, name: 'IPhone 8'} result: null
إذا تم العثور على البضائع ، نحصل على مصفوفة. إذا تم العثور على منتج واحد ، فإننا نحصل على كائن مع هذا المنتج. إذا لم يتم العثور على شيء ، في أحسن الأحوال نحصل على قيمة فارغة. في أسوأ الحالات ، تستجيب الواجهة الخلفية بـ 404 أو حتى 400 (طلب غير صحيح).
الحالات أسهل. على سبيل المثال ، تحتاج إلى الحصول على قائمة بالمتاجر في خلفية واحدة ، وإعدادات المتجر في أخرى. في بعض الأقلام لا توجد بيانات كافية ، في بعض البيانات هناك الكثير. تصفية كل هذا على العميل أو تقديم طلبات أجاكس متعددة فكرة سيئة.
فماذا يمكن أن تكون الحلول لهذه المشكلة؟ ما الذي يمكننا القيام به كمزود أمامي من جانبنا للعمل مع API ذات جودة مقبولة؟
الواجهة الأمامية
نستخدم عميل React / Redux في واجهة الشريك. تحت العميل تقع Node.js ، التي تقوم بالكثير من الأشياء المساعدة ، على سبيل المثال ، تضعها في صفحة InitialState للمحررين. إذا كان لديك عرض من جانب الخادم ، فلا يهم أي إطار عمل عميل ، على الأرجح ، يتم تقديمه بواسطة عقدة. ولكن ماذا لو ذهبت إلى أبعد من ذلك ولم تتصل مباشرة بالعميل في الخلفية ، ولكن اجعل واجهة برمجة تطبيقات الوكيل الخاصة بك على العقدة ، مصممة خصيصًا لاحتياجات العميل؟
تسمى هذه التقنية BFF (الواجهة الأمامية للواجهة الأمامية). تم تقديم هذا المصطلح لأول مرة بواسطة SoundCloud في عام 2015 ، ويمكن تصوير الفكرة بشكل تخطيطي على النحو التالي:

وبالتالي ، تتوقف عن الانتقال من رمز العميل مباشرةً إلى واجهة برمجة التطبيقات. كل مقبض وكل طريقة من واجهات برمجة التطبيقات الحقيقية التي تكررها على العقدة ومن العميل تذهب حصريًا إلى العقدة. والعقدة تقوم بالفعل بتوكيل الطلب إلى واجهة برمجة التطبيقات الحقيقية وتعيد ردًا إليك.
لا ينطبق هذا فقط على طلبات الحصول البدائية ، ولكن بشكل عام على جميع الطلبات ، بما في ذلك مع بيانات الأجزاء المتعددة / النماذج. على سبيل المثال ، يقوم متجر بتحميل ملف .xls مع كتالوجه من خلال نموذج على موقع. لذلك ، في هذا التطبيق ، لا يتم تحميل الدليل مباشرة في واجهة برمجة التطبيقات ، ولكن في مقبض Nod الخاص بك ، والذي يتدفق البروكسي إلى الواجهة الخلفية الحقيقية.
هل تتذكر هذا المثال بالنتيجة عندما ترجع الواجهة الخلفية فارغة ، أو مصفوفة أو كائن؟ الآن يمكننا إعادتها إلى وضعها الطبيعي - شيء من هذا القبيل:
function getItems (response) { if (isNull(response)) return [] if (isObject(response)) return [response] return response }
يبدو هذا الرمز فظيعًا. لأنه فظيع. لكننا ما زلنا بحاجة للقيام بذلك. لدينا خيار: قم بذلك على الخادم أو على العميل. اخترت الخادم.
يمكننا أيضًا تعيين جميع حالات الكباب والأفعى هذه بأسلوب مناسب لنا ووضع القيمة الافتراضية على الفور إذا لزم الأمر.
query: { 'feed_shoffer_id': 'feedShofferId', 'pi-from': 'piFrom', 'show-urls': ({showUrls = 'offercard'}) => showUrls, }
ما المزايا الأخرى التي نحصل عليها؟
- التصفية . يتلقى العميل فقط ما يحتاجه ، لا أكثر ولا أقل.
- التجميع لا حاجة لإضاعة شبكة العميل والبطارية لإجراء طلبات أجاكس متعددة. زيادة ملحوظة في السرعة بسبب حقيقة أن فتح الاتصال عملية مكلفة.
- التخزين المؤقت لن تجذب مكالمتك المجمعة المتكررة أي شخص مرة أخرى ، ولكنها ببساطة تعيد 304 Not Modified.
- إخفاء البيانات. على سبيل المثال ، قد يكون لديك رموز مميزة مطلوبة بين الخلفيات ولا يجب أن تذهب إلى العميل. قد لا يكون للعميل الحق حتى في معرفة وجود هذه الرموز المميزة ، ناهيك عن محتوياتها.
- الخدمات الدقيقة . إذا كان لديك قطعة متجانسة على الظهر ، فإن BFF هي الخطوة الأولى للخدمات الصغيرة.
الآن عن السلبيات.
- زيادة الصعوبة . أي تجريد هو طبقة أخرى تحتاج إلى ترميز ونشرها ودعمها. جزء متحرك آخر من الآلية التي قد تفشل.
- ازدواجية المقابض. على سبيل المثال ، يمكن أن تؤدي نقاط النهاية المتعددة نفس نوع التجميع.
- BFF عبارة عن طبقة حدودية يجب أن تدعم التوجيه العام ، والقيود المفروضة على حقوق المستخدم ، وتسجيل الاستعلام ، وما إلى ذلك.
لتسوية هذه السلبيات ، يكفي الالتزام بالقواعد البسيطة. الأول هو الفصل بين منطق الواجهة الأمامية والأعمال. لا يجب أن يقوم BFF الخاص بك بتغيير منطق الأعمال الخاص بواجهة برمجة التطبيقات الأساسية. ثانيًا ، يجب ألا تقوم الطبقة الخاصة بك بتحويل البيانات إلا عند الضرورة القصوى. نحن لا نتحدث عن واجهة برمجة تطبيقات شاملة قائمة بذاتها ، ولكن فقط عن وكيل يملأ الفجوة ، ويصحح العيوب الخلفية.
GraphQL
يتم حل مشاكل مماثلة بواسطة GraphQL. باستخدام GraphQL ، بدلاً من العديد من نقاط النهاية "الغبية" ، لديك قلم ذكي واحد يمكنه العمل مع الاستعلامات المعقدة وإنشاء البيانات بالشكل الذي يطلبه العميل.
في الوقت نفسه ، يمكن أن يعمل GraphQL على رأس REST ، أي أن مصدر البيانات ليس قاعدة البيانات ، ولكن بقية API. نظرًا للطبيعة التعريمية لـ GraphQL ، نظرًا لأن كل هذا صديق لـ React والمحررين ، يصبح عميلك أسهل.
في الواقع ، أرى GraphQL كتطبيق لـ BFF مع بروتوكول ولغة استعلام صارمة.
هذا حل ممتاز ، ولكن له العديد من العوائق ، على وجه الخصوص ، مع التصنيف ، مع تمايز الحقوق ، وبشكل عام فهو نهج جديد نسبيًا. لذلك ، لم ننتقل إليها بعد ، ولكن يبدو لي في المستقبل أنسب طريقة لإنشاء واجهة برمجة تطبيقات.
أفضل أصدقاء إلى الأبد
لن يعمل أي حل تقني بشكل صحيح بدون تغييرات تنظيمية. ما زلت بحاجة إلى وثائق ، تضمن عدم تغير تنسيق الاستجابة فجأة ، إلخ.
يجب أن نفهم أننا جميعًا في نفس القارب. بالنسبة للعميل المجرد ، سواء كان مديرًا أو مديرك ، بشكل عام ، لا فرق - لديك GraphQL هناك أو BFF. والأهم بالنسبة له أن تحل المشكلة وأن الأخطاء لا تنبثق عن همز. بالنسبة له ، لا يوجد فرق كبير بسبب الخطأ الذي حدث خطأ في المنتج - من خلال خطأ من الأمام أو الخلف. لذلك ، تحتاج إلى التفاوض مع backders.
بالإضافة إلى ذلك ، لا تظهر العيوب في الجزء الخلفي التي تحدثت عنها في بداية التقرير دائمًا بسبب الأفعال الخبيثة لشخص ما. من الممكن أن يكون للمعلمة fesh أيضًا بعض المعاني.

انتبه إلى تاريخ الالتزام. اتضح أن fesh احتفلت مؤخرًا بعيد ميلادها السابع عشر.
هل ترى بعض المعرفات الغريبة على اليسار؟ هذا هو SVN ، ببساطة لأنه لم يكن هناك غيتا في عام 2001. ليس جيثب كخدمة ، ولكن جيث كنظام تحكم إصدار. ظهر فقط في عام 2005.
التوثيق
لذا ، كل ما نحتاجه ليس الشجار مع النهاية الخلفية ، بل الاتفاق. لا يمكن القيام بذلك إلا إذا وجدنا مصدرًا واحدًا للحقيقة. يجب أن يكون هذا المصدر الوثائق.
أهم شيء هنا هو كتابة الوثائق قبل أن نبدأ العمل على الوظائف. كما هو الحال مع اتفاق ما قبل الزواج ، من الأفضل الاتفاق على كل شيء على الشاطئ.
كيف يعمل؟ نسبيًا ، سيذهب ثلاثة منهم إلى: المدير ، الواجهة الأمامية والخلفية. Fronteder ضليع في مجال الموضوع ، لذا فإن مشاركته مهمة للغاية. يجتمعون ويبدأون في التفكير في واجهة برمجة التطبيقات: بأي طرق ، ما هي الإجابات التي يجب إرجاعها ، حتى اسم وتنسيق الحقول.
اختيال
خيار جيد لوثائق API هو تنسيق Swagger ، الذي يسمى الآن OpenAPI. من الأفضل استخدام Swagger بتنسيق YAML ، لأنه بخلاف JSON ، من الأفضل قراءته من قبل البشر ، ولكن لا يوجد فرق للجهاز.
ونتيجة لذلك ، يتم إصلاح جميع الاتفاقات بتنسيق Swagger ونشرها في مستودع مشترك. يجب أن تكون وثائق واجهة المبيعات الخلفية في المعالج.
سيد محمي من عمليات ارتكاب ، رمز يدخل إليها فقط من خلال تجمع الطلبات ، لا يمكنك الدفع فيه. يلتزم ممثل الفريق الأمامي بإجراء مراجعة لتجمّع الطلبات ، بدون ترقيته ، لا يذهب الرمز إلى المعلم. هذا يحميك من التغييرات غير المتوقعة لواجهة برمجة التطبيقات دون إشعار مسبق.
كتب Swagger ، لذا اجتمعت معًا ، لذا وقعت العقد بالفعل. من هذه اللحظة ، يمكنك كواجهة أمامية أن تبدأ عملك دون انتظار إنشاء واجهة برمجة تطبيقات حقيقية. بعد كل شيء ، ما هي نقطة الفصل بين العميل والخادم ، إذا لم نتمكن من العمل بالتوازي وكان على مطوري العملاء الانتظار لمطوري الخادم؟ إذا كان لدينا "عقد" ، فيمكننا موازنة هذه المسألة بأمان.
Faker.js
فاكر رائع لهذه الأغراض. هذه مكتبة لتوليد كمية كبيرة من البيانات المزيفة. يمكن أن يولد أنواعًا مختلفة من البيانات: التواريخ والأسماء والعناوين وما إلى ذلك ، كل هذا مترجم بشكل جيد ، هناك دعم للغة الروسية.
في الوقت نفسه ، فإن الفاكر صديق مع المتعجرف ، ويمكنك رفع خادم Mock بهدوء ، والذي ، بناءً على مخطط Swagger ، سيولد إجابات وهمية لك على طول المسارات الضرورية.
التحقق
يمكن تحويل Swagger إلى مخطط json ، وبمساعدة أدوات مثل ajv ، يمكنك التحقق من استجابات الواجهة الخلفية مباشرة في وقت التشغيل ، في BFF وإبلاغ المختبرين ، والخاضعين أنفسهم ، في حالة وجود اختلافات ، إلخ.
لنفترض أن أحد المختبرين اكتشف نوعًا من الأخطاء في الموقع ، على سبيل المثال ، عند النقر على زر ، لا يحدث شيء. ماذا يفعل المختبر؟ لقد وضع تذكرة على الواجهة الأمامية: "هذا هو زرك ، لم يتم الضغط عليه ، قم بإصلاحه".
إذا كان هناك مدقق بينك وبين الخلف ، سيعلم المختبر أن الزر مضغوط بالفعل ، فقط الواجهة الخلفية ترسل إجابة خاطئة. خطأ - هذا رد لا تتوقعه الجبهة ، أي أنها لا تتوافق مع "العقد". وهنا من الضروري بالفعل إما إصلاح الظهر أو تغيير العقد.
الاستنتاجات
- نحن نشارك بنشاط في تصميم API. نصمم واجهة برمجة التطبيقات بحيث تكون ملائمة للاستخدام بعد 17 عامًا.
- نطلب وثائق Swagger. لا وثائق - لم تكتمل عملية النهاية الخلفية.
- هناك وثائق - ننشرها في بوابة ، ويجب أن يقوم ممثل الفريق الأمامي بتحديث أي تغييرات في واجهة برمجة التطبيقات.
- نرفع الخادم المزيف ونبدأ العمل على الجبهة دون انتظار واجهة برمجة التطبيقات الحقيقية.
- نضع العقدة تحت الواجهة الأمامية ونتحقق من صحة جميع الإجابات. بالإضافة إلى ذلك ، لدينا القدرة على تجميع البيانات وتطبيعها وتخزينها مؤقتًا.
انظر أيضًا
→ كيفية إنشاء واجهة برمجة تطبيقات تشبه REST في مشروع كبير
→ الواجهة الخلفية في الواجهة الأمامية
→ استخدام GraphQL كتطبيق نمط BFF