GraphQL: كيف أنقذنا واجهاتنا من جحيم البيانات “الجائعة” و”المتخمة” في عصر الـ REST

من ذكريات أبو عمر: ليلة إطلاق التطبيق البطيء

أذكرها وكأنها البارحة. كنا على وشك إطلاق تطبيق جديد لعميل مهم، تطبيق اجتماعي بسيط. الفريق كله كان متحمس، “سهرانين” لآخر الليل نضع اللمسات الأخيرة. أنا كنت مسؤولاً عن جزء من الواجهة الخلفية (Backend) وفريق الواجهة الأمامية (Frontend) كان يعمل على قدم وساق لإنهاء واجهات التطبيق على الموبايل.

بدأنا الاختبارات النهائية على شبكة 3G بطيئة لمحاكاة أسوأ الظروف… وكانت الكارثة. الصفحة الرئيسية، التي تعرض قائمة بسيطة من المستخدمين مع صورهم وأسمائهم، كانت تستغرق 10 ثوانٍ كاملة للتحميل! شعور الإحباط انتشر في الغرفة أسرع من النار في الهشيم.

زميلي في الواجهة الأمامية، شاب متحمس اسمه خالد، جاءني وعلى وجهه كل علامات اليأس وقال: “يا أبو عمر، شو القصة؟ نقطة النهاية (endpoint) اللي بترجع المستخدمين بتبعتلي “جريدة” كاملة عن كل مستخدم! تاريخ ميلاده، آخر 100 تعليق كتبها، قائمة متابعينه… وأنا كل اللي بدي ياه هو الاسم والصورة! التطبيق “متخوم” بالبيانات ومتنا ثقل.”

في المقابل، صفحة الملف الشخصي كانت تعاني من مشكلة عكسية. لعرض صفحة مستخدم واحد بكل تفاصيلها (معلوماته، آخر 5 مقالات، وعدد الإعجابات على كل مقال)، كان خالد يضطر لإرسال 7 طلبات مختلفة لواجهة برمجة التطبيقات (API)! طلب للمستخدم، طلب للمقالات، ثم 5 طلبات أخرى للحصول على تفاصيل الإعجابات لكل مقال. كانت الواجهة “جائعة” ودائماً تطلب المزيد، مما يخلق شلالاً من الطلبات التي تقتل الأداء.

تلك الليلة، أدركنا أن طريقتنا التقليدية باستخدام REST APIs، رغم قوتها، كانت تخلق لنا هذه المعضلة: إما أن نرسل بيانات أكثر من اللازم (Over-fetching) أو نجبر العميل على طلب البيانات على دفعات (Under-fetching). هنا بدأت رحلتنا للبحث عن حل، حل كان اسمه GraphQL.

ما هي مشكلة الواجهات “الجائعة” و”المتخمة”؟

قبل أن نغوص في أعماق GraphQL، دعونا نفصّل المشكلتين اللتين واجهتنا مع بنية REST التقليدية. بنية REST تعتمد على مفهوم “الموارد” (Resources). لديك مورد للمستخدمين (`/users`)، ومورد للمقالات (`/posts`)، وهكذا. كل مورد له نقطة نهاية خاصة به، وهذا التصميم هو أصل المشكلة.

الـ Over-fetching: عندما تكون الواجهة “متخمة” بالبيانات

الـ Over-fetching يعني أن الواجهة الخلفية ترسل بيانات أكثر بكثير مما تحتاجه الواجهة الأمامية لعرض ميزة معينة. هذا بالضبط ما حدث معنا في قصة إطلاق التطبيق.

تخيل أن لديك نقطة نهاية في REST API لجلب تفاصيل مستخدم:

GET /api/users/123

قد تبدو الاستجابة (Response) بهذا الشكل:

{
  "id": "123",
  "name": "أبو عمر",
  "username": "abu_omar_dev",
  "email": "abu.omar@example.com",
  "bio": "مبرمج فلسطيني يحب القهوة والكود النظيف.",
  "birthDate": "1985-01-15T00:00:00.000Z",
  "address": {
    "street": "شارع المبرمجين",
    "city": "القدس",
    "country": "فلسطين"
  },
  "followers_count": 5000,
  "following_count": 150,
  "posts": [
    { "id": "p1", "title": "مقال 1" /* ... وتفاصيل أخرى كثيرة */ },
    { "id": "p2", "title": "مقال 2" /* ... وتفاصيل أخرى كثيرة */ }
    // ... 98 مقالاً آخر
  ]
}

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

الـ Under-fetching: عندما تكون الواجهة “جائعة” للمزيد

على النقيض تماماً، يحدث الـ Under-fetching عندما لا توفر نقطة نهاية واحدة كل البيانات التي تحتاجها الواجهة الأمامية، مما يجبرها على إرسال طلبات متعددة ومتتالية للحصول على كل ما تحتاجه. وهذا ما نسميه أحياناً بمشكلة “N+1 Requests”.

لنعُد لمثال صفحة الملف الشخصي التي تحتاج لعرض:

  1. معلومات المستخدم الأساسية.
  2. آخر 3 مقالات كتبها.
  3. قائمة بأسماء أول 5 معلقين على كل مقال.

باستخدام REST، قد يبدو تسلسل الطلبات كالتالي:

  1. GET /api/users/123 (للحصول على معلومات المستخدم)
  2. GET /api/users/123/posts?limit=3 (للحصول على المقالات)
  3. GET /api/posts/p1/comments?limit=5 (للحصول على تعليقات المقال الأول)
  4. GET /api/posts/p2/comments?limit=5 (للحصول على تعليقات المقال الثاني)
  5. GET /api/posts/p3/comments?limit=5 (للحصول على تعليقات المقال الثالث)

لاحظت الكارثة؟ 5 طلبات لعرض صفحة واحدة فقط! كل طلب له زمن استجابة خاص به (latency)، وهذا يخلق تجربة استخدام بطيئة ومتقطعة. الواجهة هنا “جائعة” وتظل تطلب المزيد والمزيد من الخادم.

GraphQL يدخل المشهد: كيف غيّر قواعد اللعبة؟

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

بنية طلب GraphQL: اسأل وتحصل على ما تريد بالزبط

مع GraphQL، كل شيء يبدأ بالطلب (Query). الواجهة الأمامية تكتب طلباً يحدد الحقول التي تريدها. لنحل المشكلتين السابقتين باستخدام GraphQL.

لحل مشكلة الـ Over-fetching (الواجهة المتخمة):

واجهة الموبايل التي تريد فقط اسم المستخدم وصورته الرمزية، سترسل الطلب التالي:

query GetUserForList {
  user(id: "123") {
    name
    avatarUrl 
  }
}

وستكون الاستجابة من الخادم مطابقة تماماً لما طُلب:

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

لاحظ الجمال هنا! لا بيانات زائدة، لا إهدار للموارد. الواجهة الأمامية حصلت على ما تريده بالزبط.

لحل مشكلة الـ Under-fetching (الواجهة الجائعة):

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

query GetUserProfilePage {
  user(id: "123") {
    name
    bio
    posts(first: 3) {
      title
      content
      comments(first: 5) {
        body
        author {
          name
        }
      }
    }
  }
}

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

نقطة نهاية واحدة (Single Endpoint) تحكم كل شيء

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

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

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

هل GraphQL هو الحل لكل المشاكل؟

بكل صراحة، لا. GraphQL ليس الرصاصة الفضية التي تحل كل شيء. REST ما زال قوياً جداً ومناسباً في كثير من الحالات، خصوصاً في الواجهات البسيطة الموجهة للموارد (resource-oriented) أو عند بناء خدمات مصغرة (microservices) تتواصل فيما بينها.

نصيحة أبو عمر: GraphQL يلمع ويتألق عندما يكون لديك:

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

نصيحة عملية: ابدأ صغيراً ومغلفاً

لست مضطراً لإعادة كتابة كل واجهاتك الخلفية من الصفر. أحد أقوى الأنماط هو بناء “طبقة GraphQL” فوق واجهات REST API الحالية. يمكنك إنشاء خادم GraphQL يعمل كواجهة موحدة (façade) تتحدث مع خدمات REST القديمة في الخلفية. هذا يمنح فريق الواجهة الأمامية كل قوة GraphQL دون الحاجة لتغيير كبير في البنية التحتية الحالية. أدوات مثل Apollo Server تجعل هذا الأمر سهلاً جداً.

فكر في “Schema” أولاً

قلب أي تطبيق GraphQL هو الـ Schema (المخطط). هو العقد الرسمي بين الواجهة الأمامية والخلفية. يصف كل أنواع البيانات المتاحة والعمليات التي يمكن إجراؤها. قبل كتابة أي كود، يجب أن يجلس فريقا الواجهة الأمامية والخلفية معاً ويتفقا على شكل الـ Schema.

هذا المخطط يصبح المصدر الوحيد للحقيقة (Single Source of Truth). إليك مثال بسيط على شكل الـ Schema:

# يصف المستخدم
type User {
  id: ID!
  name: String!
  email: String
  posts: [Post!]
}

# يصف المقال
type Post {
  id: ID!
  title: String!
  author: User!
  comments: [Comment!]
}

# يصف التعليق
type Comment {
  id: ID!
  body: String!
  author: User!
}

# يصف الطلبات المتاحة
type Query {
  user(id: ID!): User
  posts: [Post!]
}

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

الخلاصة: هل حان وقت التخلي عن REST؟ 🚀

الجواب هو لا. السؤال الأصح هو: “متى أضيف GraphQL إلى صندوق أدواتي؟”. REST قدم لنا الكثير وما زال أداة رائعة. لكن عندما تبدأ واجهاتك بالمعاناة من “التخمة” و”الجوع”، وعندما يصبح التنسيق بين فرق العمل كابوساً، فإن GraphQL يقدم حلاً أنيقاً وفعالاً يعيد القوة والمرونة للواجهة الأمامية.

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

بالتوفيق في رحلتكم البرمجية!

أبو عمر

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

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

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

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

آخر المدونات

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

كان تطبيقنا حصناً منيعاً أمام ذوي الإعاقة: كيف أنقذتنا معايير الوصول (Accessibility) من جحيم الاستبعاد الرقمي؟

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

17 مايو، 2026 قراءة المزيد
الحوسبة السحابية

خوادمنا كانت نائمة 90% من الوقت: كيف أنقذتنا الحوسبة الخوادمية (Serverless) من جحيم الفواتير؟

قصة حقيقية من قلب المعركة التقنية، كيف انتقلنا من دفع فواتير ضخمة لخوادم نائمة معظم الوقت إلى نموذج فعال وموفر للتكاليف باستخدام الحوسبة الخوادمية (Serverless)....

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

كانت المقابلات التقنية كابوساً: كيف أنقذني ‘المشروع المنزلي’ من جحيم الخوارزميات على السبورة البيضاء؟

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

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

طلبات لا تنتهي؟ كيف أنقذتنا قوائم انتظار الرسائل (Message Queues) من انهيار النظام

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

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

كانت بيانات بطاقات عملائنا قنبلة موقوتة: كيف أنقذنا ‘الترميز’ (Tokenization) من جحيم تخزين البيانات الحساسة؟

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

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

من الخوادم “الثلجية” إلى الكود: كيف أنقذتنا Terraform من جحيم الانحراف التكويني

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

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

المسار المهني المزدوج: كيف أنقذنا أفضل مبرمجينا من “الترقية إلى عدم الكفاءة”؟

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

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