كانت تطبيقاتنا تغرق في البيانات: رحلتي من جحيم الـ Over-fetching في REST إلى نعيم GraphQL

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

كنا شغالين على تطبيق اجتماعي جديد، والفريق كله حماس وطاقة. الواجهات الخلفية (Backend) شغالة زي الساعة على بنية REST API محترمة، والواجهات الأمامية (Frontend) بتصاميمها الجذابة جاهزة. أطلقنا نسخة تجريبية للموظفين، وهون بلشت الشكاوى. “التطبيق بعلّق على النت الضعيف”، “ليش صفحة البروفايل بتطوّل لَتفتح؟”. كالعادة، أول اشي بنفكّر فيه هو استعلامات قاعدة البيانات أو كفاءة الكود في الخادم.

قعدت في ليلة من الليالي، فتحت أدوات المطورين (Developer Tools) وشغّلت التطبيق على محاكاة لشبكة 3G بطيئة. فتحت صفحة بروفايل مستخدم، وشفت الكارثة بعيني. طلب API واحد لصفحة البروفايل، اللي المفروض تعرض بس اسم المستخدم وصورته وكم معلومة بسيطة، كان بيرجع ملف JSON حجمه ضخم! فيه تاريخ ميلاد المستخدم، كل عناوينه المسجلة، سجل مشترياته، آخر مرة سجل فيها دخوله بالمللي ثانية، وحتى آراءه في منتجات ما الها علاقة بالتطبيق! وقتها صرخت بالفريق (طبعاً بيني وبين حالي): “يا جماعة، شو القصة؟ إحنا بنحمّل كل تاريخ حياته للمستخدم عشان نعرض صورته؟!”.

كانت هاي اللحظة هي بداية رحلتنا للبحث عن حل، رحلة أخذتنا من عالم REST المألوف إلى عالم GraphQL الواسع والفعّال.

ما هو الجحيم الذي أتحدث عنه؟ لنُعرّف الـ Over-fetching

المشكلة اللي واجهناها الها اسم تقني معروف: Over-fetching أو “جلب البيانات المفرط”. ببساطة، هي لما العميل (زي تطبيق الموبايل أو الويب) يطلب بيانات من الخادم عبر API، والخادم يرجعله بيانات أكتر بكتير من اللي بيحتاجها العميل فعلاً لعرض الصفحة الحالية.

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

  • اسم المستخدم (name)
  • صورته الشخصية (profilePictureUrl)

لكن نقطة النهاية (Endpoint) في الـ REST API اللي صممناها، /api/users/{id}، كانت مصممة عشان تكون شاملة وترجع كل معلومات المستخدم. فكانت الاستجابة (Response) اللي بترجع للتطبيق شكلها زي هيك:


{
  "id": "123",
  "name": "أبو عمر",
  "username": "abu_omar_dev",
  "email": "abu.omar@example.com",
  "profilePictureUrl": "https://.../abu_omar.jpg",
  "coverPhotoUrl": "https://.../cover.jpg",
  "bio": "مبرمج فلسطيني بحب الكنافة والـ Clean Code",
  "dateOfBirth": "1985-01-15T00:00:00.000Z",
  "address": {
    "street": "شارع الجامعة",
    "city": "رام الله",
    "country": "فلسطين"
  },
  "lastLogin": "2023-10-27T10:30:00.000Z",
  "accountCreatedAt": "2020-05-20T14:00:00.000Z",
  "purchaseHistory": [
    { "productId": "prod_a", "date": "..." },
    { "productId": "prod_b", "date": "..." }
  ],
  "userPreferences": {
    "theme": "dark",
    "notifications": true
  }
}

شايفين كمية البيانات الهائلة هاي؟ التطبيق كان محتاج بس سطرين من كل هاي “الجريدة”، ولكنه كان مضطر يستقبلها كلها، يحللها، وبعدين يتجاهلها. وهذا هو تماماً معنى “الغرق في البيانات”.

الآثار الجانبية الكارثية للـ Over-fetching

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

الـ REST API: ليست شريرة، ولكنها… محدودة في هذا السياق

هون لازم أكون منصف. الـ REST مش سيئة، بالعكس، هي بنية عظيمة خدمت الويب لعقود وما زالت تخدمه بكفاءة. هي بسيطة، مفهومة، وبتعتمد على معايير الويب (HTTP) بشكل مباشر. مشكلتها مش في تصميمها، ولكن في فلسفتها القائمة على “الموارد” (Resources).

في عالم REST، كل نقطة نهاية (Endpoint) بتمثل مورد كامل. /users هو مورد المستخدمين، و /products هو مورد المنتجات. هاي الفلسفة بتصير عبء لما يكون عندك عملاء مختلفين (موبايل، ويب، تطبيق مكتبي) وكل واحد فيهم بيحتاج جزء مختلف من نفس المورد.

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

طبعاً حاولنا نلاقي حلول ضمن عالم REST. فريق اقترح نعمل endpoint مخصص للموبايل زي /api/mobile/users/{id} يرجع بس البيانات الأساسية. وفريق تاني اقترح نستخدم معاملات الاستعلام (Query Parameters) زي /api/users/{id}?fields=name,profilePictureUrl. هاي الحلول بتشتغل، لكنها بتخلق مشاكل تانية:

  1. فوضى نقاط النهاية (Endpoint Hell): الحل الأول بيعني إنه لكل عميل جديد أو لكل شاشة جديدة، ممكن نضطر نعمل endpoint جديد. بعد فترة، بصير عندك خريطة endpoints معقدة وصعبة الصيانة، زي ما بنحكي “بتصير طوشة”.
  2. إعادة اختراع العجلة: الحل الثاني أفضل، لكنه غير معياري. كل فريق بيعمله بطريقته، وبتحتاج تكتب منطق خاص في الـ Backend عشان تحلل هاي الـ “fields” وتجيب البيانات على أساسها. إنت فعلياً بتكون قاعد بتبني نسخة مصغّرة وغير ناضجة من GraphQL بنفسك!

دخول البطل: مرحباً GraphQL

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

GraphQL مش مكتبة ولا إطار عمل، هي لغة استعلام (Query Language) للـ API، وفلسفتها بسيطة وعبقرية: “اطلب ما تحتاجه بالضبط، وستحصل عليه بالضبط، لا أقل ولا أكثر”.

بدل ما يكون عندك عشرات الـ Endpoints الثابتة، في GraphQL بيكون عندك نقطة نهاية واحدة (عادة /graphql) بتقدر ترسل إلها استعلامات معقدة. العميل هو اللي بيتحكم بشكل ونوع البيانات اللي بدو ياها، مش الخادم.

كيف أنقذتنا GraphQL؟ لنرى المثال عملياً

باستخدام GraphQL، تطبيق الموبايل اللي كان محتاج بس اسم المستخدم وصورته، صار يبعت “استعلام” (Query) للخادم شكله كالتالي:


query GetUserProfileBasic {
  user(id: "123") {
    name
    profilePictureUrl
  }
}

والخادم، اللي بيفهم لغة GraphQL، بيرجع استجابة شكلها مطابق تماماً لشكل الطلب:


{
  "data": {
    "user": {
      "name": "أبو عمر",
      "profilePictureUrl": "https://.../abu_omar.jpg"
    }
  }
}

لاحظ الجمال والبساطة! لا بيانات زيادة، لا حقول غير مستخدمة. حجم الاستجابة صار أصغر بعشرات المرات، والتطبيق صار “يحلّق” حتى على أبطأ الشبكات. أعطينا القوة للـ Frontend ليطلب اللي بيحتاجه، وارتاح الـ Backend من همّ إنشاء endpoints لكل حالة استخدام.

لكن انتظر، هناك المزيد! مشكلة الـ Under-fetching

GraphQL ما حلت بس مشكلة الـ Over-fetching، بل حلت مشكلة تانية على نفس القدر من الأهمية اسمها Under-fetching.

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

  1. طلب لـ /api/posts/{postId} عشان تجيب تفاصيل المقال.
  2. طلب لـ /api/users/{userId} عشان تجيب اسم وصورة كاتب المقال.
  3. طلب لـ /api/posts/{postId}/comments عشان تجيب التعليقات.

هون إنت بتعمل 3 رحلات ذهاب وإياب للخادم (Round trips)، وهذا بحد ذاته بطء وتأخير.

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


query GetPostPage {
  post(id: "post-456") {
    title
    content
    author {
      name
      profilePictureUrl
    }
    comments {
      text
      author {
        name
      }
    }
  }
}

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

نصائح من خبرة أبو عمر: متى تختار GraphQL؟

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

استخدم GraphQL عندما…

  • لديك عملاء متعددون: تطبيق ويب، تطبيق موبايل (iOS و Android)، ساعة ذكية… كل واحد منهم يحتاج مجموعة بيانات مختلفة. GraphQL بتخليك تخدمهم كلهم من API واحد.
  • الأداء وحجم البيانات حرج: خصوصاً في تطبيقات الموبايل اللي بتشتغل على شبكات متغيرة.
  • البيانات عندك مترابطة ومعقدة: إذا كانت بياناتك تشبه “الرسم البياني” (Graph) بطبيعتها (مستخدمين، منشورات، تعليقات، أصدقاء…)، فاسم GraphQL لم يأتِ من فراغ.
  • تريد تسريع وتيرة تطوير الواجهات الأمامية: GraphQL بتعطي مطوري الـ Frontend استقلالية كبيرة، ما بيحتاجوا يطلبوا تغييرات في الـ Backend كل مرة بيحتاجوا حقل بيانات جديد.

تمسّك بـ REST عندما…

  • الـ API بسيط جداً: إذا كان تطبيقك عبارة عن عمليات CRUD بسيطة على موارد قليلة ومستقلة، فالـ REST قد تكون أسرع وأسهل في التنفيذ.
  • * فريقك غير جاهز: GraphQL تتطلب منحنى تعلم، سواء في الـ Backend (بناء الـ Schema والـ Resolvers) أو في الـ Frontend (استخدام مكتبات زي Apollo أو Relay).

  • تعتمد بشدة على التخزين المؤقت (Caching) على مستوى HTTP: الـ REST تستفيد من الـ Caching تبع الـ HTTP بشكل رائع. في GraphQL، بما إنه كل الطلبات بتروح على endpoint واحد وبطريقة POST، فإن آليات التخزين المؤقت بتختلف وبتحتاج استراتيجية مختلفة على مستوى العميل.

الخلاصة: هل نرمي REST في سلة المهملات؟

بالتأكيد لا. القصة اللي حكيتها ما كانت عن التخلص من REST، بل عن فهم حدودها واختيار الأداة المناسبة للمشكلة المناسبة. REST ما زالت رائعة للـ Microservices، وللـ APIs العامة البسيطة، وللحالات اللي بتكون فيها الموارد واضحة ومحددة.

اللي تعلمناه من هذيك التجربة هو أهمية “تمكين العميل” (Empowering the client). GraphQL أعطت تطبيقاتنا صوت، خلتها تقدر تطلب اللي بتحتاجه بالضبط، وحولتها من تطبيقات “تغرق” في البيانات إلى تطبيقات “تسبح” برشاقة وخفة.

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

أبو عمر

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

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

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

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

آخر المدونات

تجربة المستخدم والابداع البصري

كانت واجهاتنا متحفاً للفوضى: كيف أنقذنا ‘نظام التصميم’ (Design System) من جحيم التناقض البصري؟

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

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

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

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

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

طلبات المستخدمين كانت تضيع: كيف أنقذتنا “طوابير الرسائل” (Message Queues) من جحيم فقدان البيانات؟

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

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

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

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

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

كانت بنيتنا التحتية قصراً من ورق: كيف أنقذنا Terraform من جحيم “النقرات اليدوية” والكوارث الحتمية؟

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

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

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

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

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