GraphQL: كيف تخلصنا من إرسال شاحنة لتوصيل رسالة في واجهاتنا البرمجية؟

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

شعرت بالدم يغلي في عروقي، إحنا فريق شاطر والتطبيق مكتوب بكود نظيف، شو القصة؟ نزلت على مكتبي، فتحت أدوات المطورين في المتصفح وشغلت التطبيق على المحاكي، وبديت أراقب الشبكة (Network Tab). وهون كانت الصدمة… شفت طلب API واحد لصفحة بروفايل المستخدم، حجم البيانات اللي راجعة كان بالميغابايت! الصفحة نفسها ما بتحتاج إلا اسم المستخدم وصورته وكم معلومة بسيطة، لكن الـ API كان يرجع كل تاريخ حياة المستخدم: كل منشوراته، كل تعليقاته، كل أصدقائه، حتى سجل طلباته من مطعم شاورما قريب!

وقتها ضحكت وقلت لزميلي اللي جنبي: “يا زلمة، إحنا بنبعت شاحنة نقل كبيرة عشان نوصل رسالة صغيرة مكتوبة على ورقة!”. كانت هذه هي اللحظة التي أدركت فيها أننا غارقون في جحيم الـ Over-fetching، وأن الوقت قد حان للتغيير الجذري.

ما هو الـ Over-fetching؟ أو “مشكلة الشاحنة”

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

في عالم REST API، من الشائع أن يكون لديك نقطة نهاية (Endpoint) مثل /api/users/:id. هذه النقطة مصممة لتعيد كل معلومات المستخدم. دعونا نرى مثالاً:

مثال على طلب REST تقليدي

لنفترض أن واجهة المستخدم (UI) تحتاج فقط لعرض اسم المستخدم وصورته الرمزية في رأس الصفحة. يقوم العميل بإرسال طلب GET إلى:

GET /api/users/123

لكن الخادم (Server)، الذي لا يعرف ماذا تحتاج الواجهة بالضبط، يرسل استجابة كاملة قد تبدو هكذا:


{
  "id": 123,
  "username": "abu_omar_dev",
  "email": "abu.omar@example.com",
  "fullName": "أبو عمر الفلسطيني",
  "avatarUrl": "https://example.com/avatars/123.jpg",
  "bio": "مبرمج ومطور برمجيات فلسطيني خبير في الذكاء الاصطناعي والتقنيات الحديثة...",
  "createdAt": "2020-01-15T10:00:00Z",
  "posts": [
    { "id": 1, "title": "مقالتي الأولى", "content": "..." },
    { "id": 2, "title": "مقالتي الثانية", "content": "..." }
    // ... وقد يكون هناك 500 منشور آخر
  ],
  "followers": [
    { "id": 124, "username": "user1" },
    { "id": 125, "username": "user2" }
    // ... وقد يكون هناك 10000 متابع آخر
  ]
}

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

محاولاتنا “الترقيعية” لحل المشكلة قبل GraphQL

طبعاً لم نقف مكتوفي الأيدي. حاولنا حل المشكلة بأساليب مختلفة باستخدام REST:

  • نقاط نهاية متعددة (Multiple Endpoints): قمنا بإنشاء نقاط نهاية مخصصة. مثلاً: /api/users/123/basic للحصول على المعلومات الأساسية، و /api/users/123/full للحصول على كل شيء. لكن هذا تحول إلى كابوس صيانة مع نمو التطبيق. أصبح لدينا عشرات النقاط لكل موديل (model).
  • معلمات الاستعلام (Query Parameters): استخدمنا طريقة مثل /api/users/123?fields=fullName,avatarUrl. هذا كان أفضل، لكنه لم يكن معيارياً، وكان يتطلب كتابة منطق معقد في الواجهة الخلفية لتحليل هذه المعلمات، وسرعان ما يصبح فوضوياً.

كانت هذه الحلول مجرد “ترقيع”. كنا بحاجة إلى حل جذري يغير طريقة تفكيرنا في تصميم الـ APIs.

ودخل البطل: GraphQL!

وهنا يأتي دور GraphQL. عندما سمعت عنه لأول مرة، ظننت أنه مجرد مكتبة أو إطار عمل جديد. لكنه في الحقيقة أعمق من ذلك بكثير. GraphQL هي لغة استعلام للـ APIs، وفلسفتها بسيطة وعبقرية: العميل يقرر ما يريد، والخادم يلتزم بتنفيذ طلبه بالضبط. لا زيادة ولا نقصان.

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

GraphQL على أرض الواقع: لنحل مشكلة البروفايل

باستخدام GraphQL، العملية تختلف تمامًا. أولاً، في الواجهة الخلفية، نقوم بتعريف “مخطط” (Schema) يصف كل البيانات التي يمكن للعميل طلبها وأنواعها.

1. تعريف المخطط (Schema)

يبدو المخطط الخاص بالمستخدم شيئًا كهذا (باستخدام GraphQL’s Schema Definition Language):


type User {
  id: ID!
  username: String!
  fullName: String
  avatarUrl: String
  posts: [Post!]
}

type Post {
  id: ID!
  title: String!
  content: String
}

type Query {
  user(id: ID!): User
}

هذا المخطط هو بمثابة “عقد” بين الواجهة الأمامية والخلفية. إنه يوثق نفسه بنفسه!

2. الاستعلام من العميل (The Query)

الآن، عندما تحتاج الواجهة الأمامية إلى اسم المستخدم وصورته فقط، فإنها ترسل استعلامًا (Query) يشبه JSON ولكن بدون قيم. يبدو هكذا:


query GetUserHeader {
  user(id: "123") {
    fullName
    avatarUrl
  }
}

3. الاستجابة من الخادم (The Response)

الخادم الذي يفهم GraphQL يستقبل هذا الاستعلام، ويرى بالضبط ما هي الحقول المطلوبة، ويُرجع استجابة JSON تتطابق مع بنية الاستعلام 100%:


{
  "data": {
    "user": {
      "fullName": "أبو عمر الفلسطيني",
      "avatarUrl": "https://example.com/avatars/123.jpg"
    }
  }
}

لاحظ الجمال هنا! لا بيانات إضافية، لا منشورات، لا متابعين. فقط ما طلبناه. لقد أرسلنا “دراجة هوائية” لتوصيل رسالتنا الصغيرة، وهذا بالضبط ما كنا نحتاجه. 🚲

نصائح من مطبخ أبو عمر (خبرة عملية)

بعد العمل على عدة مشاريع باستخدام GraphQL، جمعت لكم بعض النصائح العملية:

  1. لا تستبدل كل شيء دفعة واحدة: لست مضطرًا لإعادة كتابة كل واجهاتك البرمجية. يمكنك البدء بوضع واجهة GraphQL “فوق” واجهات REST الحالية. ابدأ بميزة جديدة أو بجزء من التطبيق يعاني بشدة من الـ Over-fetching.
  2. فكر في التخزين المؤقت (Caching): واجهات REST سهلة التخزين على مستوى HTTP (باستخدام GET). مع GraphQL، الأمر يتطلب استراتيجية مختلفة لأن كل الطلبات تذهب لنقطة نهاية واحدة (عادةً POST). مكتبات مثل Apollo Client و Relay لديها حلول تخزين مؤقت ذكية جدًا على مستوى العميل.
  3. احذر من مشكلة N+1: هذه مشكلة شائعة في GraphQL حيث يمكن أن يؤدي استعلام واحد من العميل إلى تنفيذ N+1 استعلام في قاعدة البيانات. لحسن الحظ، هناك حلول رائعة مثل مكتبة DataLoader التي تقوم بتجميع الاستعلامات (Batching) وحل هذه المشكلة بكفاءة.
  4. استثمر في الأدوات: النظام البيئي لـ GraphQL مليء بالأدوات الرائعة. أدوات مثل GraphiQL أو Apollo Studio تجعل استكشاف وتجربة الـ API متعة حقيقية، فهي توفر لك وثائق حية وإكمال تلقائي لاستعلاماتك.

الخلاصة: هل نرسل شاحنة أم دراجة هوائية؟ 😉

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

GraphQL ليس حلاً سحرياً لكل المشاكل، وواجهات REST ما زالت قوية ومناسبة جدًا في كثير من الحالات. لكن عندما تواجه جحيم الـ Over-fetching و الـ Under-fetching (الحاجة لعمل عدة طلبات للحصول على البيانات اللازمة)، فإن GraphQL يقدم حلاً أنيقًا وقويًا يستحق التجربة.

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

أبو عمر

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

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

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

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

آخر المدونات

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

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

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

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

كان ملفي على GitHub مقبرة للمشاريع: كيف أنقذني ملف README الشخصي من الانطباع الأول السيء؟

كان ملفي على GitHub أشبه بمقبرة للمشاريع المنسية، مما كان يعطي انطباعًا أوليًا سيئًا عني كمطور. في هذه المقالة، أشارككم كيف حوّلت هذا العبء إلى...

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

كان الخادم الوحيد على وشك الانهيار: كيف أنقذنا ‘موازن الأحمال’ (Load Balancer) من كارثة توقف الخدمة؟

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

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

كان كل عميل جديد ينتظر أسابيع: كيف أنقذتنا أتمتة ‘اعرف عميلك’ (eKYC) من جحيم قوائم الانتظار؟

أشارككم قصتي كـ"أبو عمر"، مطور فلسطيني، حول كيف انتقلنا من عملية تسجيل عملاء يدوية تستغرق أسابيع إلى نظام "اعرف عميلك" الإلكتروني (eKYC) مؤتمت بالكامل يحول...

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

كانت مفاتيحنا السرية تسافر في الدرجة السياحية (ملفات .env): كيف أنقذنا ‘مخزن الأسرار’ من كارثة التسريب؟

قصة من قلب المعركة التقنية، كيف انتقلنا من الاعتماد الخطر على ملفات .env إلى تبني "مخزن الأسرار" (Secrets Vault) كحل جذري وآمن. مقالة عملية للمطورين...

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

كان أفضل مبرمج لدينا أسوأ مدير: كيف تنقذ مسارات ‘المساهم الفردي’ أفضل مواهبك التقنية؟

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

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