جلب البيانات كان جحيماً: كيف أنقذتنا GraphQL من فوضى الـ Over-fetching و Under-fetching؟

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

بتذكر قبل كم سنة، كنا شغالين على مشروع لوحة تحكم (Dashboard) ضخمة لعميل مهم. الفكرة كانت بسيطة على الورق: صفحة رئيسية بتعرض للمستخدم معلومات حسابه، آخر منشوراته، قائمة أصدقائه، وآخر الإشعارات. “شغل بسيط” هيك حكينا لحالنا… يا ريت ضلينا ساكتين!

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

  • بدك اسم المستخدم وصورته؟ اطلب GET /api/users/{id}.
  • بدك آخر 5 منشورات؟ اطلب GET /api/users/{id}/posts?limit=5.
  • بدك قائمة الأصدقاء؟ اطلب GET /api/users/{id}/friends.
  • والإشعارات؟ طبعاً الها endpoint لحالها: GET /api/notifications?userId={id}.

النتيجة؟ الصفحة كانت بتاخد وقت طويل لتحمّل، وكنا زي اللي رايح جاي عالدكانة عشان يجيب كل غرض لحال. وفوق كل هاد، الـ endpoint تبع /api/users/{id} كان يرجّعلنا موسوعة عن حياة المستخدم من تاريخ ميلاده لعنوان بيته، مع إن كل اللي بدنا إياه هو اسمه وصورته! كل ما نطلب شغلة صغيرة من فريق الباك إند، زي مثلاً “ضيفولنا عدد اللايكات على كل منشور في الـ endpoint تبع المنشورات”، كانت تبدأ قصة طويلة عريضة واجتماعات وتعديلات ممكن تاخد أيام.

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

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

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

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

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

بتروح تطلب من الـ API التقليدي:

GET /api/v1/users/123

والرد اللي بيجيك بكون عبارة عن ملف JSON ضخم زي هيك:

{
  "id": 123,
  "username": "abu_omar_dev",
  "firstName": "عمر",
  "lastName": "أحمد",
  "email": "abu.omar@example.com",
  "profilePicture": "https://example.com/path/to/image.jpg",
  "dateOfBirth": "1985-05-20T00:00:00.000Z",
  "address": {
    "street": "شارع القدس",
    "city": "نابلس",
    "country": "فلسطين"
  },
  "phoneNumber": "+970-599-123456",
  "createdAt": "2020-01-15T10:30:00.000Z",
  "lastLogin": "2023-10-26T18:00:00.000Z",
  "isActive": true
  // ... وعشرات الحقول الأخرى
}

كل اللي كنت محتاجه هو حقلي username و profilePicture. لكنك استلمت كل هاي البيانات الزايدة. هذا يعني استهلاك أكبر للإنترنت (كارثة لمستخدمي باقات الموبايل)، وقت أطول في التحميل، ومجهود إضافي على المتصفح لمعالجة هاي البيانات. باختصار، هدر للموارد.

الـ Under-fetching: مشاوير “رايح-جاي” اللي ما بتخلص

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

في مثال لوحة التحكم تبعتنا، عشان نعرض الصفحة كاملة، كنا بنعمل سلسلة من الطلبات (Network Waterfall):

  1. الطلب الأول: جلب معلومات المستخدم الأساسية.
  2. الطلب الثاني: بعد ما يوصلنا id المستخدم، بنطلب منشوراته.
  3. الطلب الثالث: بنطلب قائمة أصدقائه.
  4. الطلب الرابع: بنطلب الإشعارات غير المقروءة.

كل طلب من هدول بيضيف وقت انتظار (latency)، والصفحة ما بتكتمل إلا بعد ما آخر طلب يرجع. هذا بيخلق تجربة مستخدم سيئة جداً، وبتحس الصفحة “بتقطّع” وهي بتحمّل.

وكيف دخلت ‘GraphQL’ على الخط وأنقذت الموقف؟

GraphQL هي لغة استعلام (Query Language) للـ API تبعك، تم تطويرها في فيسبوك عشان تحل هاي المشاكل بالتحديد. الفكرة عبقرية وبسيطة بنفس الوقت.

المبدأ بسيط: أنت تطلب، والخادم يُلبي… بالضبط!

بدل ما يكون عندك عشرات الـ endpoints وكل واحد بيرجع شكل بيانات ثابت، مع GraphQL بكون عندك endpoint واحد فقط (عادة /graphql). العميل (الـ Frontend) هو اللي بقرر شو البيانات اللي بده إياها بالزبط، عن طريق إرسال “استعلام” أو Query.

الأمر أشبه بالفرق بين البوفيه المفتوح (REST) وطلب قائمة طعام محددة (GraphQL). في البوفيه، ممكن تلاقي حالك حاطط بصحنك أكل أكثر من حاجتك. أما مع القائمة، أنت بتطلب اللي بدك إياه وبيجيك على قد طلبك، “لا زيادة ولا نقصان”.

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

query GetDashboardData {
  user(id: "123") {
    username
    profilePicture
    posts(last: 5) {
      id
      title
      likesCount
    }
    friends(first: 10) {
      id
      name
      profilePicture
    }
    notifications(unread: true) {
      id
      message
    }
  }
}

والأجمل من هيك؟ الرد اللي بيرجع من الخادم بكون بنفس شكل الطلب تماماً، بدون أي بيانات زايدة:

{
  "data": {
    "user": {
      "username": "abu_omar_dev",
      "profilePicture": "https://example.com/path/to/image.jpg",
      "posts": [
        { "id": "p1", "title": "مقالتي عن GraphQL", "likesCount": 150 },
        { "id": "p2", "title": "نصائح في الذكاء الاصطناعي", "likesCount": 230 }
      ],
      "friends": [
        { "id": "f1", "name": "خالد", "profilePicture": "..." }
      ],
      "notifications": [
        { "id": "n1", "message": "علي علّق على منشورك" }
      ]
    }
  }
}

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

نصائح من مطبخ أبو عمر: متى وكيف تستخدم GraphQL؟

بعد ما اشتغلنا على مشاريع كثيرة باستخدام GraphQL، تعلمت كم شغلة بحب أشاركها معكم.

1. لا ترمِ REST في سلة المهملات فوراً!

GraphQL مش حل سحري لكل المشاكل. معمارية REST ما زالت ممتازة جداً ومناسبة لكثير من الحالات، خصوصاً في الخدمات المصغرة (Microservices) البسيطة أو الـ APIs اللي بتتعامل مع “موارد” واضحة ومحددة. إذا كان تطبيقك عبارة عن عمليات CRUD بسيطة (Create, Read, Update, Delete) على منتجات مثلاً، يمكن REST يكون أسرع وأسهل في التطوير. “مش كل إشي بده مدفع يا جماعة، أحياناً المسدس بكفّي”.

2. ابدأ صغيراً: GraphQL فوق REST

أجمل ما في الموضوع أنك مش مضطر تعيد كتابة كل الباك إند تبعك. من الاستراتيجيات الناجحة جداً هي بناء طبقة GraphQL (GraphQL Layer) فوق الـ REST APIs الموجودة عندك. بهذه الطريقة، الـ GraphQL server تبعك بيستقبل الـ Query من العميل، وبعدين هو اللي “بيحكي” مع كل الـ REST endpoints القديمة وبجمع البيانات وبرجعها للعميل بالشكل المطلوب. هاي طريقة ممتازة للانتقال التدريجي.

3. فكّر في التخزين المؤقت (Caching)

التخزين المؤقت في GraphQL مختلف شوي عن REST. في REST، كنا بنخزن الردود بناءً على الرابط (URL) تبع الطلب، مثلاً GET /api/users/123. أما في GraphQL، كل الطلبات بتروح على نفس الـ endpoint وهو POST /graphql.

الحل يكمن في مكتبات الـ client-side مثل Apollo Client أو urql، فهي ذكية كفاية لتفهم الردود وتخزنها بناءً على نوع البيانات والـ ID تبعها. هذا بيعطي caching فعال جداً على مستوى التطبيق.

نصيحة خبير: في الباك إند، احذر من مشكلة اسمها “N+1 Query”. لحلها، استخدم نمط اسمه DataLoader. هو عبارة عن أداة بتجمع كل الطلبات المتشابهة في طلب واحد كبير لقاعدة البيانات، وهذا بحسّن الأداء بشكل خيالي.

4. أمّن الـ Endpoint الخاص بك

لأن GraphQL مرنة جداً، ممكن مستخدم خبيث يبعت طلب معقد جداً ومتشعب (deeply nested query) بهدف إنه يستهلك كل موارد الخادم ويعطله.

لهيك، لازم تطبق آليات حماية مثل:

  • تحديد عمق الطلب (Query Depth Limiting): منع الطلبات اللي بتتشعب أكثر من حد معين.
  • تحليل تعقيد الطلب (Query Complexity Analysis): إعطاء “تكلفة” لكل حقل في الـ Schema، ورفض أي طلب بتتجاوز تكلفته الإجمالية حداً معيناً.
  • تحديد مهلة زمنية (Timeout): إيقاف أي طلب بياخد وقت أطول من اللازم.

الخلاصة: هل GraphQL هو المستقبل؟ 🚀

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

هل هي بديل كامل لـ REST؟ لا أعتقد. لكل أداة مكانها وزمانها. لكن في عالم التطبيقات الحديثة اللي واجهاتها معقدة ومتشابكة (مثل تطبيقات الموبايل، Single-Page Applications)، أثبتت GraphQL أنها أداة لا يمكن الاستغناء عنها.

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

أبو عمر

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

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

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

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

آخر المدونات

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

استعلاماتنا كانت تزحف كالسلحفاة: كيف أنقذتنا ‘فهارس قاعدة البيانات الذكية’ من جحيم بطء الأداء؟

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

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

مساهماتي في المصادر المفتوحة كانت حلمًا مؤجلًا: كيف أنقذتني ‘قضايا المبتدئين الجيدة’ (Good First Issues) من جحيم ‘من أين أبدأ؟’

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

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

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

أشارككم قصة حقيقية عن انهيار كاد أن يدمر سمعتنا، وكيف كان نمط تصميم بسيط مثل "قاطع الدائرة" (Circuit Breaker) هو طوق النجاة. سنتعلم معاً كيف...

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

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

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

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

خوادمنا كانت كائنات ثلجية فريدة: كيف أنقذنا ‘Ansible’ من جحيم ‘الانحراف في الإعدادات’ (Configuration Drift)؟

أنا أبو عمر، وهذه قصتي مع "الانحراف في الإعدادات" (Configuration Drift)، الكابوس الصامت الذي يحوّل خوادمك المنظمة إلى فوضى من "الكائنات الثلجية" الفريدة. اكتشف كيف...

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

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

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

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

تغطية الكود 100% كانت وهمًا: كيف أنقذنا ‘الاختبار الطفري’ (Mutation Testing) من جحيم الاختبارات عديمة الفائدة؟

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

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