GraphQL: كيف أنقذنا من جحيم الاستعلامات الزائدة والناقصة (Over/Under-fetching)؟

يا جماعة الخير، السلام عليكم ورحمة الله.

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

أنا كنت مسؤول عن ربط الواجهات الأمامية (الـ Frontend) بالخلفية (الـ Backend) عن طريق واجهة برمجية (API) من نوع REST. في البداية، الأمور كانت “تمام التمام”. صفحة المنتجات بتجيب المنتجات، صفحة المستخدم بتجيب معلومات المستخدم… كل إشي ماشي زي الساعة.

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

  1. يرسل طلب لـ /api/user/123 عشان يجيب معلومات المستخدم.
  2. بعد ما يرجع الجواب، يرسل طلب ثاني لـ /api/user/123/favorites?limit=5 عشان يجيب المنتجات المفضلة.
  3. وبعدها، يرسل طلب ثالث لـ /api/user/123/comments?limit=3 عشان يجيب التعليقات.

ثلاث رحلات كاملة للخادم بس عشان نعرض صفحة واحدة! التطبيق صار بطيء “زي السلحفاة”، خصوصًا على اتصالات الإنترنت الضعيفة. والزبون كل يوم يتصل ويحكي: “يا أبو عمر، التطبيق بعلّق!”. وإحنا رايحين جايين نعدّل في الـ Endpoints، مرة ندمج بيانات عشان نقلل الطلبات، فيصير عنا (Over-fetching)، ومرة نفصلها عشان نكون أدق، فيصير عنا (Under-fetching). حسينا حالنا في حلقة مفرغة، جحيم من الاستعلامات اللي ما بتخلص. لحد ما قررنا نوقف ونقول: “خلص، لازم نلاقي حل جذري”.

وهون يا جماعة الخير، كانت بداية رحلتنا مع GraphQL، المنقذ اللي خلّصنا من كل هاللخمة.

ما هي مشكلة الاستعلامات الزائدة والناقصة (Over/Under-fetching)؟

قبل ما نغوص في تفاصيل GraphQL، خلونا نفهم بالزبط شو هي المشكلة اللي كنا بنواجهها مع واجهات REST التقليدية. المشكلة بتتلخص في مفهومين أساسيين:

الاستعلام الزائد (Over-fetching)

هذا بصير لما الخادم يرجعلك بيانات أكثر من اللي أنت محتاجها في الواجهة. تخيل إنك بدك تعرض قائمة بأسماء المستخدمين، فبترسل طلب لـ GET /api/users. الخادم، بكل كرمه، برجعلك لكل مستخدم اسمه، إيميله، تاريخ ميلاده، عنوانه، وكل قصة حياته! وأنت كل اللي كان بيلزمك هو الاسم بس.

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

الاستعلام الناقص (Under-fetching)

هذا هو الوجه الآخر للمشكلة، وهو اللي حكيت عنه في قصتي فوق. بصير لما طلب واحد ما برجعلك كل البيانات اللي محتاجها، فتضطر تعمل “رحلات” إضافية للخادم. بدك تعرض منشور والتعليقات عليه؟

  • الطلب الأول: GET /posts/1 لجلب المنشور.
  • الطلب الثاني: GET /posts/1/comments لجلب التعليقات.

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

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

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

لا زيادة ولا نقصان. أنت تطلب، والخادم يُلبي طلبك بحذافيره.

كيف يعمل GraphQL؟ المكونات الأساسية

عشان نفهم سحر GraphQL، لازم نعرف مكوناته الثلاثة الرئيسية:

  1. المخطط (Schema): هذا هو العقد أو “الكاتالوج” اللي بيوصف كل البيانات الممكن طلبها من الواجهة. هو بمثابة “مصدر الحقيقة الأوحد” (Single Source of Truth). في المخطط، أنت بتعرّف أنواع البيانات (Types) والعلاقات بينها.

    مثلاً، لو بدنا نمثل قصة التطبيق اللي حكيتها:

    
    type User {
      id: ID!
      name: String
      avatar: String
      favorites(limit: Int): [Product]
      comments(limit: Int): [Comment]
    }
    
    type Product {
      id: ID!
      name: String
      price: Float
    }
    
    type Comment {
      id: ID!
      text: String
    }
    

    هذا المخطط بيحكي للجميع: “يا جماعة، أنا بقدر أزوّدكم ببيانات من نوع User و Product و Comment، وهاي هي الحقول المتاحة في كل نوع”.

  2. الاستعلامات (Queries): هذا هو الجزء اللي بستخدمه العميل عشان يطلب البيانات. جمال GraphQL يكمن في إن شكل الاستعلام بيشبه تمامًا شكل استجابة JSON اللي رح ترجع.

    فبدل ما نعمل 3 طلبات REST، الآن بنعمل طلب GraphQL واحد زي هيك:

    
    query GetHomePageData {
      user(id: "123") {
        name
        avatar
        favorites(limit: 5) {
          name
          price
        }
        comments(limit: 3) {
          text
        }
      }
    }
    

    والنتيجة اللي بترجع من الخادم بتكون مطابقة تمامًا للشكل اللي طلبناه:

    
    {
      "data": {
        "user": {
          "name": "أبو عمر",
          "avatar": "url/to/avatar.jpg",
          "favorites": [
            { "name": "كيبورد ميكانيكي", "price": 75.0 },
            { "name": "شاشة 4K", "price": 350.0 }
          ],
          "comments": [
            { "text": "منتج رائع!" },
            { "text": "أنصح به بشدة." }
          ]
        }
      }
    }
    

    رحلة واحدة فقط! لا زيادة ولا نقصان. “بالزبط” زي ما بدنا.

  3. المُحلِّلات (Resolvers): هذه هي “العقول المدبرة” في الخادم. المُحلِّل هو عبارة عن دالة (function) مسؤولة عن جلب البيانات لحقل معين في المخطط. لما يوصل استعلام GraphQL للخادم، الخادم بيمشي على كل حقل في الاستعلام وبستدعي المُحلِّل الخاص فيه. هذا بيعطيك قوة هائلة، لأنك ممكن تجيب البيانات من أي مكان: قاعدة بيانات SQL، قاعدة بيانات NoSQL، واجهة REST أخرى، أو حتى ملف نصي!

نصائح من “أبو عمر”: متى تستخدم GraphQL؟

الحكي بيناتنا، GraphQL مش حل لكل المشاكل، وهو مش دايماً البديل الأفضل لـ REST. استخدام الأداة المناسبة في المكان المناسب هو اللي بيميز المبرمج الخبير. من خلال تجربتي، هاي هي الحالات اللي GraphQL بيبدع فيها:

  • تطبيقات الموبايل والواجهات الأمامية المعقدة (SPAs): لما يكون استهلاك البيانات وسرعة الاستجابة عامل حاسم، GraphQL هو صديقك الصدوق لأنه بيقضي على مشكلة الطلبات المتعددة.
  • أنظمة مبنية على الخدمات المصغرة (Microservices): إذا كان عندك واجهة أمامية بتحتاج تجمع بيانات من عدة خدمات خلفية، ممكن تبني طبقة GraphQL (Gateway) بتوحّد كل هاي الخدمات في واجهة واحدة متماسكة.
  • تعدد المنصات (Web, Mobile, IoT): لما يكون عندك عدة عملاء بمتطلبات بيانات مختلفة، GraphQL بيسمح لكل عميل يطلب بس اللي بيحتاجه، بدون ما تضطر تعمل endpoint مخصص لكل واحد.
  • تمكين فرق الواجهات الأمامية: GraphQL بيعطي مطوري الواجهات الأمامية استقلالية كبيرة. ما في داعي يظلوا يطلبوا تعديلات من فريق الخلفية كل ما تغير تصميم الواجهة. بيقدروا ببساطة يعدلوا استعلام GraphQL ويحصلوا على البيانات الجديدة فورًا (طالما هي موجودة في المخطط).

بالمقابل، ممكن REST يظل خيار أفضل في الحالات التالية:

  • التطبيقات البسيطة جدًا: إذا تطبيقك عبارة عن CRUD بسيط على مورد واحد، “ليش نغلّب حالنا؟”. REST ممكن يكون أسرع وأسهل في التنفيذ.
  • الواجهات العامة المفتوحة (Public APIs): بساطة REST ونموذج “المورد” (Resource) المألوف قد يكون أسهل للفهم والاستخدام من قبل المطورين الخارجيين.
  • عندما يكون التخزين المؤقت (Caching) على مستوى HTTP أولوية قصوى: التخزين المؤقت في REST أسهل ومباشر باستخدام أكواد حالة HTTP، بينما في GraphQL الأمر يتطلب استراتيجيات أكثر تعقيدًا على مستوى العميل.

الخلاصة: لا تكن أسير واجهاتك البرمجية 🚀

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

GraphQL جاء كأداة قوية لحل مشكلة محددة ومؤلمة: عدم الكفاءة في جلب البيانات. هو مش “الرصاصة الفضية” اللي بتحل كل إشي، ولكنه أداة بتمنحك مرونة وقوة هائلة لما تحتاجها.

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

أبو عمر

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

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

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

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

آخر المدونات

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

كانت خوادمنا تلتهم الميزانية وهي خاملة: كيف أنقذتنا ‘الحوسبة بلا خوادم’ (Serverless) من جحيم التكاليف الخفية؟

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

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

مقابلات الألغاز أم المشاريع العملية؟ كيف أنقذتنا “المشاريع المنزلية” من توظيف كوارث برمجية

كنا نختار أذكى "حلّالي الألغاز" ثم نتفاجأ بفشلهم في العمل الحقيقي. في هذه المقالة، أسرد لكم يا جماعة الخير كيف غيرنا نهجنا في التوظيف بالكامل...

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

كان خطأ واحد ينهار نظامنا بأكمله: كيف أنقذنا ‘نمط قاطع الدائرة’ من جحيم الفشل المتتالي؟

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

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

كانت دفاترنا لا تتطابق أبداً: كيف أنقذنا ‘نظام التسوية الآلي’ من جحيم الأخطاء المالية الصامتة؟

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

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

كانت حاوياتنا جزراً منعزلة: كيف أنقذنا Kubernetes من جحيم التنسيق اليدوي؟

أشارككم قصة من أرض المعركة التقنية، كيف انتقلنا من فوضى إدارة حاويات Docker اليدوية إلى عالم الأتمتة المنظم مع Kubernetes. مقالة عملية للمطورين ومسؤولي الأنظمة...

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

كانت معرفتي التقنية تتلاشى: كيف أنقذني نظام ‘الدماغ الثاني’ من جحيم إعادة اختراع العجلة؟

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

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