كنا نغرق في بحر الاستدعاءات: كيف أنقذنا 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. هي بتعطي القوة والمرونة للواجهات الأمامية، وبتقلل الاعتمادية على الفريق الخلفي لكل تغيير صغير، والأهم من كل هاد، بتحسن تجربة المستخدم النهائية بتطبيقات أسرع وأكثر استجابة.

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

أبو عمر

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

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

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

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

آخر المدونات

الحوسبة السحابية

كانت بيئاتنا جزرًا من الفوضى: كيف أنقذتنا “البنية التحتية كشفرة” (IaC) من جحيم الانحراف التكويني؟

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

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

مقابلاتي التقنية كانت كارثة: كيف أنقذني ‘التفكير بصوت عالٍ’ من جحيم الفشل؟

أشارككم قصة شخصية عن فشلي في المقابلات التقنية بسبب الصمت القاتل، وكيف غيرت استراتيجية "التفكير بصوت عالٍ" مساري المهني. اكتشفوا معي كيف تحولون المقابلة من...

30 مايو، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

كان مستخدمونا في الطرف الآخر من العالم ينتظرون إلى الأبد: كيف أنقذتنا شبكات توصيل المحتوى (CDN) من جحيم زمن الاستجابة المرتفع؟

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

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

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

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

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

ميزانيات الخطأ (Error Budgets): كيف أنهت كابوس مكالمات منتصف الليل وأنقذتنا من الإرهاق؟

كنا غارقين في مكالمات طوارئ ليلية لا تنتهي، فريق منهك والمنتج على المحك. في هذه المقالة، أشارككم قصة كيف أنقذنا مفهوم "ميزانيات الخطأ" (Error Budgets)...

30 مايو، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

كانت اجتماعاتنا الفردية استجواباً صامتاً: كيف حولنا الـ 1-on-1 من تقرير حالة ممل إلى محرك لنمو الفريق؟

أشارككم تجربتي كقائد فريق تقني في تحويل الاجتماعات الفردية (1-on-1s) من جلسات استجواب مملة إلى محادثات مثمرة تساهم في بناء الثقة وتطوير الفريق. هذه المقالة...

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

كانت اختباراتنا تصرخ ‘الذئب’: كيف قضينا على ‘الاختبارات المتقلبة’ (Flaky Tests) واستعدنا الثقة في خطوط الأنابيب؟

في هذه المقالة، أشارككم قصة من أرض المعركة البرمجية، وكيف تغلب فريقي على كابوس "الاختبارات المتقلبة" أو Flaky Tests. سنغوص في أسبابها الخفية، ونتعلم استراتيجيات...

30 مايو، 2026 قراءة المزيد
أدوات وانتاجية

كانت أصابعي تصرخ من التكرار: كيف أنقذتني ‘مقتطفات الشفرة’ (Code Snippets) من جحيم كتابة Boilerplate؟

أشارككم قصتي مع التكرار الممل في البرمجة وكيف غيرت "مقتطفات الشفرة" (Code Snippets) طريقة عملي تماماً. دليل عملي من مبرمج فلسطيني لزيادة إنتاجيتك والتخلص من...

30 مايو، 2026 قراءة المزيد
أتمتة العمليات

كانت تبعياتنا قنبلة موقوتة: كيف أنقذنا ‘التحديث الآلي للتبعيات’ من جحيم الثغرات الأمنية المنسية؟

أشارككم قصة حقيقية عن ليلة كادت فيها ثغرة أمنية في إحدى المكتبات المنسية أن تدمر مشروعنا بالكامل. اكتشفوا معنا كيف تحولنا من الفوضى إلى الأمان...

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