أنماط المعمارية

الواجهات الخلفية المخصصة للواجهات الأمامية (BFF)

18 دقيقة الدرس 7 من 10

الواجهات الخلفية المخصصة للواجهات الأمامية (BFF)

حين تُطلق فرق المنتج تطبيقاتها عبر الويب والهاتف المحمول وتكاملات الجهات الخارجية في آنٍ واحد، تبدأ واجهة برمجة التطبيقات الموحدة ذات الأغراض العامة بالتصدع تحت وطأة المتطلبات المتضاربة. يحتاج تطبيق الهاتف إلى حمولات بيانات خفيفة تُراعي البطارية؛ ولوحة التحكم على المتصفح بيانات غنية مجمّعة في رحلة واحدة؛ وواجهة الشريك الخارجية إصداراتٍ صارمة وموارد ذات تفاصيل أوسع. محاولة إرضاء الثلاثة من خلفية واحدة تُفضي إلى الأسوأ: واجهة برمجة تطبيقات تعجّ بمفاتيح ?fields= وتفاوض على الإصدارات وأساليب مخصصة لكل منصة مخبّأة في الشيفرة المشتركة.

نمط الواجهات الخلفية المخصصة للواجهات الأمامية (BFF) — شاعه Sam Newman في SoundCloud ثم وُثِّق نمطًا رسميًّا — يحلّ هذا التوتر بمنح كل نوع عميل مستقل طبقةً خلفيةً رفيعةً مصمَّمة خصيصًا لتلك الواجهة.

ما هو الـ BFF؟

الـ BFF مكوِّن على جانب الخادم يجلس بين عميل محدد (ويب، iOS، Android، تلفزيون ذكي، واجهة برمجة شريك) والخدمات المصغرة أو واجهات الدومين في المراحل الخلفية. يتحدث لغة العميل: يعرف بالضبط البيانات التي تحتاجها الشاشة، وبأي شكل، وبأي مستوى تفصيل. يُجمِّع نداءات خدمات متعددة، ويحوِّل الحمولات، ويُطبِّق تدفقات المصادقة الخاصة بالعميل، ويُخفي تعقيدات الطبقات الخلفية.

الأهم من ذلك أن الـ BFF يمتلكه الفريق ذاته الذي يمتلك العميل. فريق iOS يمتلك BFF الخاص بـ iOS. هذا يُزيل عبء التنسيق مع فريق API مشترك لإضافة نقطة نهاية خاصة بالجوال — فريق الجوال يُسلِّمها بنفسه.

BFF pattern — each client type gets its own dedicated backend Web App Browser Mobile App iOS / Android Partner API 3rd Party Web BFF GraphQL / REST Aggregates + SSR data Mobile BFF REST / Protocol Buf Lean payloads, push Partner BFF REST (versioned) OAuth2, rate limits User Service profiles, prefs Order Service cart, checkout Product Service catalog, pricing Notification Svc push, email, SMS Ownership Web BFF ← Frontend Team Mobile BFF ← Mobile Team Partner BFF ← Platform Team Each team deploys independently
نمط BFF: ثلاثة أنواع من العملاء، وثلاث واجهات خلفية مخصصة، وكلها تستدعي الخدمات المصغرة المشتركة ذاتها.

المشكلة التي تُحدثها واجهة API موحدة

بدون BFF تضطر الخلفية الموحدة إلى استيعاب كل عميل في آنٍ واحد. هذا يُفرز أنماط فشل معروفة:

  • الجلب الزائد (Over-fetching). لوحة التحكم على الويب تريد 40 حقلًا لكل منتج، وبطاقة الجوال تحتاج 5 فقط. نقطة النهاية المشتركة تُعيد 40 حقلًا، فكل طلب جوال يحمل 35 حقلًا غير ضروري. على شبكة 3G بطيئة مع 100 عنصر في قائمة، تضيف هذه الزيادة مئات الميلي ثانية وتستنزف البطارية.
  • الجلب الناقص (Under-fetching). الشاشة الرئيسية للجوال تحتاج بيانات من خدمة المستخدمين والطلبات والمنتجات في رندر واحد. الـ REST API المشترك الذي يعكس حدود الخدمات يُجبر العميل على ثلاثة طلبات منفصلة. وعلى الجوال كل رحلة ذهاب وإياب تضيف 100-300 ميلي ثانية.
  • الاقتران والخوف من التغيير. حين تعتمد عشرات العملاء على واجهة API واحدة، يُخاطر كل تغيير بكسر أحدهم. يتقلَّص الفريق مشلولًا يُضيف حقولًا اختيارية ويُبقي نقاط النهاية القديمة للأبد (/v1، /v2، /v3…).
  • تعقيد المصادقة والجلسة. الجلسات القائمة على الكوكيز مناسبة للمتصفحات لكنها خاطئة لتطبيقات الجوال. الـ JWTs ملائمة للجوال لكن غير مرغوب فيها في المتصفحات بسبب مخاطر XSS. نقطة نهاية واحدة لا تستطيع تحقيق الأمثلية لكليهما دون منطق تفريعي.
قصة نشأة النمط في SoundCloud: ابتكر Sam Newman نمط BFF حين كان في SoundCloud نحو عام 2015. كان فريق API الموحد يتحكم في كل الوصول للخلفية. كلما أراد فريق iOS أو Android نقطة نهاية جديدة فتحوا تذكرة وانتظروا. إضافة BFF مخصص للجوال — يمتلكه فريق الجوال — كسر هذه العقبة وقلّص وقت وصول المميزات أسابيع.

ما الذي ينتمي إلى الـ BFF

الـ BFF رفيع بتعمُّد. مسؤولياته هي:

  1. التجميع. التفرع إلى N خدمة مصغرة بالتوازي ثم دمج الردود في حمولة واحدة مُحسَّنة للعميل.
  2. التحويل. إعادة تسمية الحقول، وتسطيح الهياكل المتداخلة، وتحويل الوحدات، وتطبيق التنسيق الخاص بالعميل (صيغ التاريخ، رموز العملة، أحجام الصور).
  3. تكييف المصادقة. تبادل الرموز المميزة، وتطبيق استراتيجية الجلسة الصحيحة لذلك العميل (كوكيز للويب، JWTs قصيرة العمر للجوال، مفاتيح API للشركاء)، وإعادة توجيه هوية المستخدم للخدمات التالية.
  4. التخزين المؤقت في الطبقة المناسبة. يستطيع BFF الويب تخزين الردود المجمَّعة في Redis مفهرسةً بالمستخدم والصفحة، مما يُقلِّص النداءات المتكررة للخدمات الخلفية.
  5. أعلام الميزات ومنطق الاختبار A/B. تقديم أشكال ردود مختلفة بناءً على تعيين التجربة — دون تلويث الخدمات المصغرة بمنطق تجارب UI.

ما لا يجب أن يحتويه الـ BFF: منطق الأعمال الجوهري، والكتابة في قاعدة البيانات، والتحقق من الثوابت الدومينية. هذه تنتمي إلى الخدمات المصغرة. متى بدأ BFF بأعمال دومينية أصبح خدمةً بحد ذاتها وينبغي إعادة تسميته وفقًا لذلك.

Mobile BFF request flow — fan-out aggregation and payload trimming Mobile App 1 request GET /home Mobile BFF 1. Auth check 2. Fan-out (parallel) 3. Trim + reshape 4. Return 5 fields ~25ms total parallel User Service 40 fields returned Order Service 20 fields returned Product Service 35 fields returned 5 fields Payload savings 95 fields received total 5 fields sent to client ~95% bandwidth reduction
BFF الجوال يتفرع إلى ثلاث خدمات بالتوازي، ويُقلِّص 95 حقلًا إلى 5، ويُعيد ردًّا خفيفًا واحدًا للتطبيق.

الـ BFF مقابل بوابة API

كثيرًا ما يخلط الطلاب بين الـ BFF وبوابة API. إنهما أدوات مختلفة لمهام مختلفة:

  • بوابة API بنيةٌ تحتية: تتولى الشواغل المشتركة لكل الحركة — إنهاء TLS، وتحديد معدل الطلبات، والتحقق من JWT، والتوجيه. فهي لا تعرف شيئًا عن العميل وتمتلكها فرقة المنصة.
  • الـ BFF هاجسٌ منتجي: يعرف نموذج البيانات، وتخطيط الشاشة، وأنماط التفاعل لعميل واحد محدد. تمتلكه فرقة المنتج التي تمتلك العميل.

في معظم المعماريات يتعايشان معًا. تسير الطلبات: العميل ← بوابة API (بنية تحتية) ← BFF (منتج) ← الخدمات المصغرة. البوابة تتولى رموز المصادقة وتحديد المعدل؛ والـ BFF يتولى التجميع وإعادة التشكيل.

المقايضات ومتى لا تستخدم الـ BFF

الـ BFF ليس مجانيًّا. المقايضات الحقيقية هي:

  • تكرار الشيفرة. ثلاثة BFFs غالبًا ما تحتوي منطق تجميع متشابه. في الفرق الصغيرة، هذا التكرار قد يفوق الفائدة. استخدم مكتبة مشتركة أو انقل المنطق المشترك إلى الخدمات المصغرة.
  • قفزة شبكية إضافية. كل طلب يمر الآن بنداء شبكي إضافي. عند الكمون المنخفض (خدمات مُستضافة في الشبكة الداخلية ذاتها) يكون هذا أقل من 1 ميلي ثانية عادةً — مقبول. لكنه تكلفة حقيقية.
  • قطع متحركة أكثر تتطلب تشغيلًا. ثلاثة BFFs تعني ثلاث خدمات للمراقبة والنشر والتوسعة. لفريق من 3 مهندسين، واجهة API واحدة مع نقاط نهاية خاصة بالعميل هو الاختيار الصحيح على الأرجح.
ابدأ بـ BFF واحد لا بثلاثة. إن كان لديك تطبيق ويب اليوم وربما تبني جوالًا لاحقًا، ابدأ بـ BFF واحد. حين يتشكَّل فريق الجوال وتتباعد احتياجاته تباعدًا ملموسًا، قسِّمه. النمط لا يُلزم بنسبة 1:1 منذ اليوم الأول — بل يُلزم بتوافق متعمَّد بين العميل والخلفية.
النمط المضاد: الـ "BFF السمين". الفرق التي تسمح بتسرب منطق الأعمال إلى الـ BFF تنتهي بالأسوأ من العالمين: طبقة مترابطة يصعب اختبارها وإعادة استخدامها ومشاركتها. أنفِذ قاعدة صارمة: الـ BFF يُحوِّل ويُجمِّع فقط؛ لا يتحقق أبدًا من الثوابت الدومينية ولا يكتب مباشرة في قاعدة البيانات.

التبني في العالم الواقعي

أصبح الـ BFF ممارسةً معيارية في الشركات التي تُشغِّل منتجات متعددة الأسطح. تستخدم Netflix طبقة "edge API" شبيهة بالـ BFF (Falcor/GraphQL) تُخصِّص الردود لتطبيق التلفزيون والجوال والويب. تحتفظ Spotify بطبقات بوابة منفصلة لكل سطح عميل. بنت Zalando أحد أشهر تطبيقات BFF المُوثَّقة علنًا، ووصفت كيف يُجمِّع BFF الويب والجوال من أكثر من 50 خدمة مصغرة لكل منهما. كما يُعدّ النمط مناسبًا بالفطرة لـ GraphQL: يُصبح الـ BFF خادم GraphQL يحلّ الحقول باستدعاء خدمات REST في الخلفية، مانحًا العميل تحكمًا دقيقًا في شكل البيانات التي يتلقاها.

الخلاصة

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