كنا نغرق في بحر الاستدعاءات: كيف أنقذنا GraphQL من جحيم الـ over-fetching والـ under-fetching؟

السلام عليكم يا جماعة الخير،

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

في البداية، كالعادة، استخدمنا REST APIs. وهون بلشت المعاناة. الواجهة الأمامية (Frontend) كانت تصرخ! عشان يعرضوا صفحة بروفايل وحدة، كانوا مضطرين يبعتوا طلب (request) عشان يجيبوا معلومات المستخدم، وبعد ما يرجع الجواب، يبعتوا طلب ثاني لمنشوراته، وطلب ثالث لأصدقائه، وطلبات متتالية لكل منشور عشان يجيبوا تعليقاته… كنا حرفيًا نغرق في بحر من استدعاءات الـ API. الوضع كان أشبه بالواحد اللي بروح على مطعم وبطلب كل صحن لحال، وبستنى بين كل صحن والثاني عشر دقايق. الأداء كان في الحضيض، والتطبيق بطيء جدًا.

وقتها قعدنا وحكينا: “يا جماعة، شو القصة؟ لازم يكون في حل أحسن من هالحكي”. وبعد بحث وتجربة، لقينا طوق النجاة اللي أنقذنا من هذا الجحيم: GraphQL.

ما هو جحيم الـ Over-fetching والـ Under-fetching؟

قبل ما نحكي عن الحل، خلينا نفهم أصل المشكلة بالزبط. المشكلتين هدول هما من أشهر عيوب بنية REST API التقليدية لما نتعامل مع تطبيقات معقدة.

المشكلة الأولى: الجلب الزائد (Over-fetching)

ببساطة، الـ Over-fetching بيصير لما الـ API يرجعلك بيانات أكثر من اللي بتحتاجها. تخيل إنك بدك تعرض قائمة بأسماء المستخدمين وصورهم الشخصية بس. لكن نقطة النهاية (endpoint) اللي عندك، اللي هي /api/users، بترجعلك كل اشي عن كل مستخدم: الاسم، الصورة، تاريخ الميلاد، الإيميل، العنوان، آخر مرة كان متصل، وقائمة طويلة من البيانات اللي ما بتلزمك حاليًا.

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

المشكلة الثانية: الجلب الناقص (Under-fetching)

هاي المشكلة هي الوجه الآخر للعملة، وهي اللي صارت معنا في قصة البروفايل. الـ Under-fetching بيصير لما نقطة النهاية ما ترجعلك كل البيانات اللي بتحتاجها في طلب واحد، فبتضطر تعمل طلبات إضافية.

مثالنا هو الأوضح:

  1. GET /users/1 لجلب معلومات المستخدم.
  2. GET /users/1/posts لجلب منشورات المستخدم.
  3. GET /users/1/followers لجلب متابعي المستخدم.

هذا السيناريو، اللي بنسميه “N+1 problem”، كارثي على أداء التطبيق وبيخلق تعقيد كبير في كود الواجهة الأمامية اللي لازم ينسق بين كل هاي الطلبات.

GraphQL: المنقذ الذي يمنحك القوة

هنا يأتي دور GraphQL. GraphQL مش لغة برمجة ولا هي مكتبة، هي لغة استعلام (Query Language) للـ API تم تطويرها في فيسبوك عام 2012 ونُشرت كمشروع مفتوح المصدر في 2015. الفكرة العبقرية وراها بسيطة جدًا:

بدل ما يكون الخادم (Server) هو اللي يقرر شكل وحجم البيانات اللي برجعها، العميل (Client) هو اللي بطلب بالزبط شو بده، وبالشكل اللي بده ياه، والخادم برد عليه بنفس الشكل تمامًا.

تخيلها كأنك رايح على بوفيه مفتوح. مع REST، أنت بتطلب “الوجبة رقم 5” وبتاخد كل إشي فيها سواء عجبك أو لأ. مع GraphQL، أنت بتمر على البوفيه وبتعبي صحنك بالزبط بالأشياء اللي بتحبها وبالكميات اللي بدك إياها. إشي مرتب!

كيف تعمل GraphQL على أرض الواقع؟

على عكس REST اللي بيعتمد على نقاط نهاية (endpoints) متعددة، GraphQL عادةً بتستخدم نقطة نهاية واحدة (مثل /graphql). العميل بيبعت طلب من نوع POST لهاي النقطة، وجسم الطلب (body) بيحتوي على الاستعلام.

النظام كله بيعتمد على 3 مفاهيم أساسية:

1. المخطط (Schema)

هو العقد أو “المنيو” اللي بين الخادم والعميل. أنت كمطور خلفية (backend) بتعرف كل أنواع البيانات الممكنة (Types) والعمليات المتاحة عليها (Queries, Mutations). هذا المخطط هو مصدر الحقيقة الوحيد، وبيسمح للفرق الأمامية والخلفية يشتغلوا بشكل مستقل.


# مثال على Schema بسيط
type User {
  id: ID!
  name: String
  email: String
  posts: [Post]
}

type Post {
  id: ID!
  title: String
  content: String
  comments(limit: Int = 5): [Comment]
}

type Comment {
  id: ID!
  text: String
  author: User
}

# العمليات المتاحة للقراءة
type Query {
  user(id: ID!): User
}

2. الاستعلامات (Queries)

هذا هو الطلب اللي ببعته العميل. العميل بيكتب استعلام بيشبه شكل JSON، وبيحدد فيه الحقول اللي بده إياها بالضبط.

لحل مشكلة صفحة البروفايل اللي حكينا عنها، بدل ما نبعت 5 أو 6 طلبات REST، بنبعت استعلام GraphQL واحد كالتالي:


query GetUserProfile {
  user(id: "1") {
    id
    name
    profilePicture
    posts(limit: 10) {
      title
      comments(limit: 5) {
        text
        author {
          name
        }
      }
    }
    followers(limit: 20) {
      name
      profilePicture
    }
  }
}

والجميل في الموضوع؟ الجواب اللي بيرجع من الخادم بيكون بنفس شكل الاستعلام بالزبط! لا زيادة ولا نقصان.

3. المُحلّلات (Resolvers)

هي “العضلات” اللي بتشتغل في الخفاء. لكل حقل (field) في المخطط تبعك، بيكون في دالة (function) على الخادم اسمها “resolver”. هاي الدالة هي المسؤولة عن جلب البيانات لهذا الحقل تحديدًا. ممكن تجيبها من قاعدة بيانات، من API ثاني، من ملف… من أي مكان.

الخادم لما يستقبل استعلام GraphQL، بيمشي على حقوله واحد واحد وبينفذ الـ resolver الخاص فيه. هذا بيعطي مرونة وقوة هائلة للخادم.

نصائح عملية من خبرة أبو عمر

بعد سنوات من الشغل على GraphQL، تعلمت كم شغلة مهمة بحب أشاركها معكم:

  • GraphQL ليست بديلاً كاملاً لـ REST: لا تفكر إنك لازم ترمي كل شغل REST اللي عندك. REST ما زالت ممتازة للتطبيقات البسيطة، أو لما تكون طبيعة البيانات ثابتة جدًا، أو في عمليات مثل رفع الملفات. فكر في GraphQL كأداة قوية في صندوق أدواتك، استخدمها لما تكون هي الحل الأنسب للمشكلة.
  • ابدأ صغيرًا: مش ضروري تحول كل نظامك لـ GraphQL مرة واحدة. ممكن تبدأ بميزة جديدة أو بجزء معقد من تطبيقك الحالي وتعمله بـ GraphQL. كثير من الشركات بتشغل GraphQL و REST جنبًا إلى جنب.
  • انتبه للأداء والأمان: بما أن العميل صار عنده قوة كبيرة، ممكن يكتب استعلامات معقدة جدًا تسبب ضغطًا هائلاً على الخادم (مثلاً يطلب 10 مستويات متداخلة من البيانات). لازم تستخدم أدوات مثل تحديد عمق الاستعلام (query depth limiting) أو تحليل تكلفة الاستعلام (query cost analysis) عشان تحمي الخادم من الاستعلامات الخبيثة أو السيئة.
  • التخزين المؤقت (Caching): التخزين المؤقت في GraphQL مختلف شوي عن REST. في REST، بتقدر تخزن استجابة GET /users/1 كاملة. في GraphQL، بما أنه كل الطلبات بتروح على نقطة نهاية واحدة (POST /graphql)، التخزين على مستوى HTTP بصير أصعب. الحل بيكون في التخزين على مستوى العميل (باستخدام مكتبات مثل Apollo Client أو Relay) اللي بتفهم استجابات GraphQL وبتقدر تخزن الكيانات (entities) بشكل ذكي.

الخلاصة: هل يجب أن أستخدم GraphQL؟ 💡

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

GraphQL نقلة نوعية في طريقة تفكيرنا ببناء الـ APIs. هي بتعطي القوة والمرونة للواجهات الأمامية، وبتقلل الاعتمادية على الفريق الخلفي لكل تغيير صغير، والأهم من كل هاد، بتحسن تجربة المستخدم النهائية بتطبيقات أسرع وأكثر استجابة.

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

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

برمجة وقواعد بيانات

تحديثات قاعدة البيانات بدون توقف: كيف أنقذنا نمط التوسيع والتعاقد (Expand/Contract) من جحيم التوقفات المجدولة؟

هل سئمت من إيقاف الخدمة مع كل تحديث لهيكلة قاعدة البيانات؟ أشارككم قصة حقيقية وكيف أنقذنا نمط التوسيع والتعاقد (Expand/Contract) من ليالي النشر الطويلة والمُجهدة،...

4 يونيو، 2026 قراءة المزيد
الشبكات والـ APIs

كانت إعادة المحاولة كارثة: كيف أنقذتنا مفاتيح عدم تكرار العمليات (Idempotency Keys) من جحيم الفواتير المزدوجة؟

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

4 يونيو، 2026 قراءة المزيد
الحوسبة السحابية

من التوقف التام إلى النجاة: كيف أنقذتنا استراتيجية “الضوء المرشد” (Pilot Light) يوم انقطعت السحابة؟

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

4 يونيو، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

كانت مهمتي البرمجية للاختبار مجرد كود: كيف أنقذني توثيق القرارات من جحيم الصمت بعد المقابلة؟

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

4 يونيو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

من الانتظار لأيام إلى الدفع في ثوانٍ: كيف أنقذتنا شبكات الدفع الفوري من جحيم التحويلات البنكية؟

أسرد لكم من واقع تجربتي كـ "أبو عمر"، كيف عانينا من بطء وتكلفة التحويلات البنكية الدولية، وكيف جاءت شبكات الدفع الفوري ومعيار ISO 20022 لتكون...

4 يونيو، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

كان كل خادم لدينا ‘ندفة ثلج’ فريدة: كيف أنقذنا ‘الكود كبنية تحتية’ (IaC) من جحيم الانجراف اليدوي؟

في هذه المقالة، أشارككم قصة حقيقية من قلب المعركة التقنية مع "خوادم ندفات الثلج" الفوضوية. سنغوص في مفهوم "الكود كبنية تحتية" (IaC) وكيف أن أدوات...

4 يونيو، 2026 قراءة المزيد
اختبارات الاداء والجودة

كانت تغطية الاختبارات 100% لكن الأخطاء تتسرب: كيف أنقذنا “الاختبار الطفري” من جحيم الثقة الزائفة؟

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

4 يونيو، 2026 قراءة المزيد
البودكاست