كنا نغرق في بحر من الطلبات: كيف أنقذنا GraphQL من جحيم الـ ‘Over-fetching’ و ‘Under-fetching’؟

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

كنا شغالين على تطبيق ضخم، فيه واجهة ويب للمدراء، وتطبيق موبايل للمستخدمين، ولوحة تحكم داخلية للموظفين. كل هدول الواجهات بتسحب بياناتها من نفس الـ API اللي بنيناه باستخدام معمارية REST المعتادة. في البداية، كان كل شي تمام التمام، شغل مرتب ومبسوطين على حالنا. لكن مع كبر المشروع وزيادة التعقيدات، بلشت المشاكل تظهر زي الفطر بعد الشتا.

أذكر تماماً تلك الليلة، كنا بنحاول نطلق نسخة جديدة من تطبيق الموبايل. التطبيق كان بطيئاً جداً في التحميل، والمستخدمون يشتكون. المشكلة كانت واضحة: صفحة المستخدم الرئيسية بتحتاج فقط اسم المستخدم وصورة البروفايل، لكن الـ endpoint تبعنا /api/users/:id كان يرجع “كل شروة خروة” عن المستخدم: تاريخ ميلاده، عنوانه، سجل مشترياته، آخر 50 تعليق، وأشياء ما إلها لزوم أبداً في هذا السياق. كنا نرسل حمولة بيانات بحجم 200 كيلوبايت عشان نعرض معلومتين حجمهم ما بيجي 1 كيلوبايت! العميل على التلفون، والمدير فوق راسنا، والقهوة صارت مرة زيادة عن اللزوم. في هذيك اللحظة، كنا نغرق حرفياً في بحر من البيانات غير الضرورية.

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

ما هو الـ Over-fetching والـ Under-fetching؟ خلينا نبسّطها

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

مشكلة الـ Over-fetching: لما تجيب “كل الدكان” عشان علبة كبريت

هذه هي بالضبط المشكلة اللي حكيتلكم عنها في قصتي. الـ Over-fetching بيصير لما العميل (تطبيق الموبايل مثلاً) يطلب بيانات من الـ API، والـ API يرجعله بيانات أكثر بكثير من اللي بيحتاجها فعلياً.

تخيل أنك تطلب من الـ API بيانات مستخدم لعرضها في قائمة الأصدقاء. كل ما تحتاجه هو الاسم والصورة الشخصية. لكن الـ REST API المصمم بطريقة “Resource-Oriented” التقليدية، سيرجع لك كل بيانات المستخدم المخزنة في قاعدة البيانات.

مثال على طلب REST:

GET /api/users/1

الاستجابة (Over-fetching):

{
  "id": 1,
  "username": "abu_omar_dev",
  "name": "أبو عمر",
  "email": "abuomar@example.com",
  "avatar_url": "https://example.com/avatar.jpg",
  "bio": "مبرمج فلسطيني...",
  "date_of_birth": "1985-01-15",
  "address": {
    "street": "شارع القدس",
    "city": "رام الله",
    "country": "فلسطين"
  },
  "last_login": "2023-10-27T10:00:00Z",
  "posts_count": 150,
  "followers_count": 2500
  // ... والمزيد من البيانات غير اللازمة
}

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

مشكلة الـ Under-fetching: مشاوير “رايح جاي” عشان تجيب أغراض السهرة

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

تخيل لوحة التحكم في مشروعنا. في صفحة واحدة، نحتاج نعرض تفاصيل المستخدم، وآخر 5 مقالات كتبها، وأول 3 تعليقات على كل مقال. باستخدام REST API تقليدي، السيناريو سيكون كالتالي:

  • الطلب الأول: جيب لي بيانات المستخدم /api/users/1
  • الطلب الثاني: جيب لي مقالات هذا المستخدم /api/users/1/posts
  • الطلب الثالث: جيب لي تعليقات المقال الأول /api/posts/101/comments
  • الطلب الرابع: جيب لي تعليقات المقال الثاني /api/posts/102/comments
  • وهكذا…

هذه الطلبات المتتالية (Waterfall of requests) كارثية على الأداء. كل طلب له زمن استجابة خاص به، والمجموع الكلي يكون بطيئاً جداً، خاصة على شبكات الموبايل الضعيفة.

صديقنا المنقذ: لغة الاستعلام GraphQL

هنا يأتي دور GraphQL، وهي ليست مكتبة أو إطار عمل بحد ذاتها، بل هي لغة استعلام (Query Language) للـ APIs، ومعيار جديد تم تطويره في فيسبوك عام 2012 لحل هذه المشاكل تحديداً.

شو قصة GraphQL؟

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

هذا يعني أننا ننتقل من عالم فيه عشرات أو مئات الـ endpoints الثابتة، إلى عالم فيه endpoint واحد فقط (عادة /graphql) يستقبل كل أنواع الاستعلامات.

كيف يعمل السحر؟ (مع أمثلة كود)

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

حل مشكلة الـ Over-fetching

تطبيق الموبايل يحتاج فقط الاسم والصورة. ببساطة، يرسل هذا الاستعلام:

query GetUserHeader {
  user(id: "1") {
    name
    avatar_url
  }
}

والاستجابة ستكون بالضبط ما طلبه، لا زيادة ولا نقصان:

{
  "data": {
    "user": {
      "name": "أبو عمر",
      "avatar_url": "https://example.com/avatar.jpg"
    }
  }
}

لاحظ كيف أن العميل هو من حدد الحقول (name, avatar_url) التي يريدها. شغل مرتب ونظيف!

حل مشكلة الـ Under-fetching

لوحة التحكم التي تحتاج بيانات متداخلة ومعقدة، يمكنها الآن الحصول على كل ما تحتاجه في طلب واحد فقط:

query GetDashboardData {
  user(id: "1") {
    name
    email
    posts(first: 5) {
      title
      content
      comments(first: 3) {
        body
        author {
          name
        }
      }
    }
  }
}

الاستجابة ستكون عبارة عن ملف JSON واحد يحتوي على كل هذه البيانات المتشعبة، بنفس الهيكلية التي طلبناها. وداعاً لمشاوير “رايح جاي”!

REST مقابل GraphQL: ليست حرباً، بل لكل مقام مقال

الآن قد يقول قائل: “خلص يا أبو عمر، يعني نكب كل شغلنا بالـ REST ونروح على GraphQL؟”. الجواب هو: لا، مهلاً يا صديقي. المسألة ليست حرباً بين التقنيتين. لكل أداة مكانها وزمانها.

  • متى تختار REST؟ لا يزال REST خياراً ممتازاً، وربما أفضل، في حالات مثل:
    • الـ APIs البسيطة جداً التي لا تتطلب مرونة كبيرة.
    • الـ APIs العامة والمفتوحة التي تخدم آلاف المطورين وتحتاج إلى استقرار وثبات في هيكل البيانات.
    • عندما تكون الاستفادة من آليات التخزين المؤقت (Caching) الخاصة بـ HTTP أمراً حيوياً وسهلاً (لأن كل endpoint له URL فريد).
  • متى يلمع نجم GraphQL؟
    • التطبيقات التي لها واجهات متعددة ومختلفة (ويب، موبايل، ساعة ذكية).
    • التطبيقات ذات الواجهات المعقدة التي تتطلب بيانات متداخلة من مصادر مختلفة.
    • عند التعامل مع معمارية الخدمات المصغرة (Microservices)، حيث يمكن لطبقة GraphQL أن تكون واجهة موحدة تجمع البيانات من عدة خدمات خلفية.
    • عندما يتطور التطبيق بسرعة وتحتاج الواجهات الأمامية إلى بيانات جديدة بشكل مستمر دون الحاجة لانتظار فريق الواجهات الخلفية لتعديل الـ endpoints.

نصائح من “أبو عمر” لبداية رحلتك مع GraphQL

إذا تحمست للموضوع وقررت أن تخوض التجربة، اسمح لي أن أقدم لك بعض النصائح من خبرتي المتواضعة:

  1. ابدأ صغيراً: لا تحاول إعادة كتابة كل شيء من الصفر. يمكنك بناء طبقة GraphQL فوق الـ REST API الموجود لديك. هذا يسمى (Wrapping)، وهو أسلوب رائع للبدء والتعلم دون مخاطرة كبيرة.
  2. فكر بالـ Schema أولاً: الـ Schema أو “المخطط” هو قلب الـ API في GraphQL. هو العقد بين الواجهة الأمامية والخلفية. استثمر وقتاً في تصميمه بشكل جيد وواضح.
  3. استخدم الأدوات المساعدة: البيئة المحيطة بـ GraphQL غنية جداً. استخدم مكتبات مثل Apollo (Client/Server) أو Relay لتسهيل حياتك. أدوات مثل GraphiQL أو GraphQL Playground لا غنى عنها للتجربة والاختبار.
  4. لا تهمل الأمان والأداء: المرونة الكبيرة لـ GraphQL تأتي مع مسؤوليات. تعلم عن كيفية منع الاستعلامات الخبيثة أو المعقدة جداً (Query Depth Limiting)، وكيفية حل مشكلة الـ (N+1 Problem) الشهيرة باستخدام تقنيات مثل الـ Data Loader.

الخلاصة: هل GraphQL هي الحل السحري؟ 🔮

بعد كل هالحكي، هل GraphQL هي العصا السحرية التي ستحل كل مشاكلنا؟ الجواب هو لا. لا يوجد حل سحري في عالم البرمجة. GraphQL هي أداة قوية جداً، قدمت حلاً عبقرياً لمشاكل حقيقية ومؤلمة كنا نعاني منها مع REST في سياقات معينة.

إنها نقلة نوعية في التفكير، من “مجموعة موارد ثابتة” إلى “رسم بياني للبيانات” يمكن للعميل استكشافه بحرية. تعلمها وفهم فلسفتها سيفتح أمامك آفاقاً جديدة ويضيف سلاحاً قوياً إلى ترسانة أدواتك كمطور.

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

أبو عمر

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

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

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

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

آخر المدونات

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

تحديثات قاعدة البيانات بدون توقف: كيف أنقذنا نمط التوسيع والتعاقد (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 قراءة المزيد
البودكاست