كانت تطبيقاتنا تطلب بيانات الكون كله: كيف أنقذنا GraphQL من جحيم الـ Over-fetching؟

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

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

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

أنا وفريقي حطينا راسنا براس بعض، مش فاهمين شو اللي بصير. قعدت أمسك التطبيق وأحلل الشبكة (Network analysis)، وفتحت الـ Log… وهنا كانت الصدمة. اكتشفت إنه عشان نحمّل الصفحة الشخصية للمستخدم، اللي هي بتحتاج بس اسمه وصورته وكم معلومة بسيطة، الـ API تبعنا كان يرجع ملف JSON حجمه ٢ ميجابايت! 😱

كان طلب الـ API الواحد لـ /api/user/123 بيرجع كل تاريخ حياة المستخدم: كل بوستاته، كل تعليقاته، كل أصدقائه، إعداداته الخاصة، سجل مشترياته… باختصار، كان بيرجع “بيانات الكون كله” زي ما بحكي العنوان. قعدت صافن في الشاشة وبحكي لحالي: “يا زلمة، شو هاد؟ ليش كل هاي البيانات عشان نعرض سطرين؟”.

هذا الجحيم اللي كنا عايشين فيه اسمه تقنياً “Over-fetching”، وكان هو السبب في قتل أداء تطبيقنا. ومن هنا بدأت رحلتنا للبحث عن حل، رحلة انتهت بحب من أول نظرة مع تقنية اسمها GraphQL.

جحيم واجهات برمجة التطبيقات التقليدية (REST API)

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

المشكلة الأولى: الجلب الزائد (Over-fetching)

زي ما صار معنا بالضبط. أنت بتطلب معلومة صغيرة، لكن الخادم (Server) مصمم يرجعلك كل المعلومات المتعلقة بهذا الطلب في “قالب” ثابت. تخيل أنك تريد فقط اسم المستخدم من نقطة النهاية (Endpoint) التالية /api/users/1، ولكنك تحصل على هذا:


{
  "id": 1,
  "name": "أبو عمر",
  "username": "abu_omar_dev",
  "email": "email@example.com",
  "address": {
    "street": "شارع يافا",
    "city": "القدس",
    "zipcode": "91000"
  },
  "phone": "1-770-736-8031",
  "website": "abuomar.dev",
  "company": {
    "name": "شركة البرمجة المتقدمة",
    "catchPhrase": "نحو كود نظيف"
  },
  // ... والكثير الكثير من البيانات الأخرى
}

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

المشكلة الثانية: الجلب الناقص والطلبات المتعددة (Under-fetching & N+1 Problem)

هذه هي الوجه الآخر للعملة. أحيانًا، لا تكفي نقطة نهاية واحدة. تخيل أنك تريد عرض صفحة مؤلف مع آخر 3 مقالات له. باستخدام REST، ستحتاج على الأغلب لعمل التالي:

  1. الطلب الأول: جلب بيانات المؤلف من /api/users/1.
  2. الطلب الثاني: جلب مقالات هذا المؤلف من /api/users/1/posts.

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

مرحباً بـ GraphQL: لغة الاستعلام التي تطلبها بنفسك

القصة وما فيها، GraphQL هي لغة استعلام (Query Language) لواجهات برمجة التطبيقات، تم تطويرها في فيسبوك عام 2012 لحل هذه المشاكل بالضبط. الفكرة عبقرية في بساطتها: بدلًا من أن يقرر الخادم ما هي البيانات التي سيرسلها، يقوم العميل (Client) بتحديد البيانات التي يحتاجها بالضبط.

لا أكثر ولا أقل. أنت تطلب ما تريد، وتحصل على ما طلبت.

كيف يعمل هذا السحر؟ لنقارن بين REST و GraphQL

لنفترض نفس السيناريو: نريد اسم المؤلف وعناوين آخر 3 مقالات له.

الطريقة التقليدية (REST)

كما ذكرنا، ستحتاج على الأقل لطلبين:

  1. GET /api/users/1
  2. GET /api/users/1/posts?limit=3

وهذا يسبب تأخيرًا ملحوظًا في تحميل الصفحة.

طريقة GraphQL السحرية

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


query GetAuthorWithPosts {
  user(id: "1") {
    name
    posts(last: 3) {
      title
    }
  }
}

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


{
  "data": {
    "user": {
      "name": "أبو عمر",
      "posts": [
        { "title": "لماذا نستخدم Next.js؟" },
        { "title": "مقدمة إلى Docker" },
        { "title": "دليلك الشامل لـ TypeScript" }
      ]
    }
  }
}

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

أبو عمر، كيف أبدأ مع GraphQL؟

سؤال ممتاز. البداية قد تبدو صعبة، لكنها أسهل مما تتوقع. GraphQL يتكون من جزأين رئيسيين: الخادم والعميل.

على جهة الخادم (Backend)

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

المكونات الأساسية للمخطط:

  • Types: تصف أنواع الكائنات في نظامك (مثل User, Post, Comment).
  • Queries: تصف الطرق المتاحة لجلب البيانات (عمليات القراءة).
  • Mutations: تصف الطرق المتاحة لتعديل البيانات (عمليات الإنشاء، التحديث، الحذف).

مثال بسيط لمخطط (Schema)

هذا مثال بسيط بلغة تعريف المخطط (SDL) لتطبيق مدونة:


# يصف كائن المقال
type Post {
  id: ID!
  title: String!
  content: String
  author: User!
}

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

# نقطة الدخول لجلب البيانات
type Query {
  # جلب كل المقالات
  allPosts: [Post!]
  # جلب مقال محدد بالـ ID
  postById(id: ID!): Post
  # جلب مستخدم محدد بالـ ID
  userById(id: ID!): User
}

بعد تعريف المخطط، تستخدم مكتبة مثل Apollo Server (لـ Node.js) أو Graphene (لـ Python) لربط هذا المخطط مع دوال (Resolvers) تجلب البيانات الفعلية من قاعدة البيانات.

على جهة العميل (Frontend)

الوضع أسهل بكثير. يمكنك استخدام مكتبة عميل مثل Apollo Client أو Relay. هذه المكتبات تسهل عملية إرسال الـ Queries والـ Mutations، وتوفر ميزات رائعة مثل التخزين المؤقت (Caching) وإدارة الحالة (State Management) تلقائيًا.

ببساطة، تكتب استعلامك في الواجهة الأمامية، والمكتبة تتكفل بالباقي.

نصائح من “الختيار”: متى تختار GraphQL؟

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

نصيحة عملية: قبل أن تقرر استخدام GraphQL، اسأل نفسك: هل أعاني حقًا من مشاكل الـ Over-fetching أو الـ Under-fetching؟ هل لدي عدة عملاء (ويب، موبايل، iOS) يحتاجون بيانات مختلفة من نفس المصدر؟

  • استخدم GraphQL إذا:
    • تطبيقك يحتوي على واجهات معقدة تحتاج بيانات من مصادر متعددة (مثل فيسبوك).
    • تطور تطبيقات موبايل حيث كل بايت من البيانات يهم.
    • لديك فرق متعددة (Frontend, Backend, Mobile) وتحتاج لعقد قوي (Schema) بينها.
    • تريد تطوير الـ API الخاص بك بسرعة بدون الحاجة لعمل إصدارات (v1, v2, v3).
  • فكر مرتين قبل استخدام GraphQL إذا:
    • الـ API الخاص بك بسيط جدًا (مثلاً، Microservice يؤدي وظيفة واحدة).
    • فريقك ليس لديه الوقت لتعلم التقنية الجديدة والمنحنى التعليمي الخاص بها.
    • مشروعك بسيط جدًا لدرجة أن REST API التقليدي يفي بالغرض وزيادة.

الخلاصة: هل هي النهاية لـ REST؟

بالتأكيد لا. REST API ما زالت قوية ومفيدة جدًا في الكثير من الحالات، خصوصًا في الخدمات المصغرة (Microservices) والـ APIs البسيطة.

لكن GraphQL قدمت حلاً ثوريًا لمشاكل حقيقية كانت تواجه المطورين في التطبيقات الحديثة والمعقدة. لقد حررت مطوري الواجهات الأمامية من الاعتماد الكامل على فريق الواجهات الخلفية لتصميم الـ Endpoints، ومنحتهم القوة لطلب ما يريدون بالضبط.

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

قد تكون GraphQL هي الأداة التي كانت ناقصاك لتنقل مشاريعك إلى مستوى آخر من الكفاءة والسرعة. بالتوفيق يا جماعة الخير! 🚀

أبو عمر

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

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

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

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

آخر المدونات

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

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

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

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

كانت إجاباتي في المقابلات عشوائية: كيف أنقذتني منهجية STAR من جحيم أسئلة “حدثنا عن موقف…”؟

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

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

كيف أنقذ ‘موازن الحمل’ خادمنا الوحيد من الانهيار؟ قصة من قلب المعركة

هل يواجه تطبيقك بطئًا وتوقفًا مفاجئًا مع زيادة عدد المستخدمين؟ في هذه المقالة، أشارككم قصتي مع انهيار خادمنا الوحيد وكيف كان 'موازن الحمل' (Load Balancer)...

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

من كشط الشاشة إلى الخدمات المصرفية المفتوحة: كيف أنقذت واجهات الـ API تطبيقاتنا المالية؟

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

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

وداعاً لـ `kubectl apply -f`: كيف حولنا إدارة Kubernetes إلى عملية آلية وموثوقة مع GitOps؟

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

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

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

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

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

كانت عملياتنا كالدومينو: كيف أنقذنا “منسق سير العمل” من جحيم الفشل المتتالي؟

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

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