تطبيقي المونوليثي كان وحشًا: كيف أنقذني نمط ‘التين الخانق’ (Strangler Fig) من جحيم التحديث المستحيل؟

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

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

المشكلة؟ كان وحشًا لا يمكن المساس به. كل ما نحاول نضيف ميزة جديدة، حتى لو كانت بسيطة زي تغيير لون زر، “بتولع” الدنيا وبتبدأ المشاكل تظهر في أماكن ما إلها أي علاقة. فريق التطوير كان مرعوبًا من مجرد التفكير في عمل “deploy” جديد. كنا في جحيم حقيقي اسمه “التحديث المستحيل”. أذكر مرة طلب منا مدير المنتج إضافة بوابة دفع جديدة… يا زلمة، قعدنا شهرين بس بنحاول نفهم كيف الكود مربوط ببعضه، وفي النهاية فشلنا فشلًا ذريعًا وتسببنا بتوقف النظام لساعات.

في ليلة من ليالي الإحباط، وأنا ببحث عن حلول سحرية، قرأت مقالة لمارتن فاولر عن نمط معماري اسمه “نمط التين الخانق” (Strangler Fig Pattern). الاسم غريب، بس الفكرة كانت عبقرية وبسيطة لدرجة إنها بدت كطوق نجاة أُرسل لنا من السماء. ومن هنا، بدأت رحلة ترويض الوحش.

ما هو التطبيق المونوليثي؟ ولماذا هو جحيم متنقل؟

قبل ما ندخل في تفاصيل الحل، خلينا نوصف المشكلة صح. التطبيق المونوليثي هو تطبيق تم بناؤه كوحدة واحدة متكاملة. كل شيء – واجهة المستخدم، منطق العمل (Business Logic)، الوصول للبيانات – كله موجود في قاعدة كود واحدة (codebase) ويتم تشغيله كعملية واحدة (single process).

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

أبرز مشاكل المونوليث:

  • صعوبة التحديث: أي تغيير صغير يتطلب اختبار وإعادة نشر التطبيق بأكمله، مما يزيد من المخاطرة والوقت.
  • التعقيد المتزايد: مع مرور الوقت، يصبح الكود متشابكًا لدرجة يصعب معها فهمه أو صيانته. نسميه بالعامية “كود معكرونة” (Spaghetti Code).
  • صعوبة التوسع (Scalability): إذا كان جزء واحد فقط من التطبيق عليه ضغط كبير (مثلاً، خدمة البحث)، يجب عليك عمل نسخة كاملة من التطبيق لتلبية هذا الضغط، وهذا هدر كبير للموارد.
  • قيود التكنولوجيا: أنت عالق مع التقنيات التي بدأ بها المشروع. هل تريد تجربة لغة برمجية جديدة أو قاعدة بيانات أحدث؟ حظًا موفقًا في إقناع المونوليث بذلك!

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

شجرة التين الخانقة: طوق النجاة من الطبيعة

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

هذه هي الفكرة بالضبط في عالم البرمجيات! بدلاً من إعادة كتابة التطبيق المونوليثي بالكامل في مشروع ضخم ومحفوف بالمخاطر (Big Bang Rewrite)، نقوم ببناء النظام الجديد تدريجيًا “حول” النظام القديم. ومع مرور الوقت، يأخذ النظام الجديد وظائف القديم قطعة قطعة، حتى “يختنق” النظام القديم تمامًا ويمكننا إيقافه بأمان.

كيف طبّقت نمط الخانق خطوة بخطوة؟ (قصة ترويض الوحش)

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

الخطوة الأولى: بناء “الواجهة الخانقة” (The Strangler Façade)

أول وأهم خطوة هي وضع “وسيط” بين المستخدمين والتطبيق المونوليثي. هذا الوسيط هو الذي سيقوم بتوجيه الطلبات. في حالتنا، كان هذا الوسيط عبارة عن Reverse Proxy بسيط باستخدام NGINX (يمكن استخدام أي تقنية مشابهة مثل API Gateway أو حتى قطعة برمجية بسيطة).

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

# NGINX Configuration - Phase 1
# All traffic goes to the old monolith

server {
    listen 80;
    server_name my-awesome-app.com;

    location / {
        # Proxy all requests to the legacy monolith
        proxy_pass http://legacy-monolith-app:8080;
        proxy_set_header Host $host;
    }
}

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

الخطوة الثانية: بناء الخدمة المصغرة الجديدة

بدأ فريق صغير بالعمل على بناء خدمة مصغرة (Microservice) جديدة لإدارة المنتجات. استخدمنا تقنيات حديثة (Node.js و MongoDB) مما أعطى الفريق دفعة معنوية هائلة. هذه الخدمة الجديدة لها قاعدة بياناتها الخاصة ومنطقها الخاص.

ركزنا فقط على وظائف قراءة المنتجات في البداية (GET requests) لتكون المخاطرة أقل ما يمكن.

الخطوة الثالثة: الخنق التدريجي (The Fun Part!)

هنا يبدأ السحر. قمنا بتحديث إعدادات NGINX. الآن، أي طلب يبدأ بـ /api/products سيتم توجيهه إلى الخدمة المصغرة الجديدة. أي طلب آخر (مثل /api/orders أو /api/users) سيظل يذهب إلى المونوليث القديم.

# NGINX Configuration - Phase 2
# Strangling the products API

upstream monolith_server {
    server legacy-monolith-app:8080;
}

upstream new_products_service {
    server new-products-microservice:3000;
}

server {
    listen 80;
    server_name my-awesome-app.com;

    # STRANGLE: Route product-related traffic to the new service
    location /api/products {
        proxy_pass http://new_products_service;
        proxy_set_header Host $host;
    }

    # All other traffic still goes to the monolith
    location / {
        proxy_pass http://monolith_server;
        proxy_set_header Host $host;
    }
}

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

الخطوة الرابعة: التكرار حتى الاختناق الكامل

بعد نجاح “خنق” خدمة المنتجات، كررنا العملية. أخذنا الجزء المؤلم التالي، وهو “إدارة الطلبات” (Orders). بنينا خدمة مصغرة جديدة لها، وقمنا بتحديث الواجهة الخانقة لتوجيه طلبات /api/orders إليها. وهكذا دواليك.

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

نصائح من مطبخ أبو عمر 👨‍🍳

هذا النمط ليس سهلاً دائماً، وهذه بعض النصائح من تجربتي الشخصية:

  • ابدأ صغيرًا وآمنًا: اختر جزءًا من النظام لا يمثل خطورة كبيرة كبداية. وظائف القراءة (Read-only) هي مرشح مثالي لأول عملية خنق.
  • الرصد والمراقبة هما عيناك: يجب أن يكون لديك نظام مراقبة (Monitoring) ولوحات متابعة (Dashboards) قوية. أنت بحاجة لمعرفة أداء الخدمة الجديدة، وكمية الطلبات التي يتم توجيهها، وأي أخطاء تحدث في الواجهة الخانقة. بدونها، أنت تقود وأنت أعمى.
  • مزامنة البيانات هي التحدي الأكبر: في كثير من الأحيان، ستحتاج الخدمة الجديدة والمونوليث القديم إلى الوصول إلى نفس البيانات أثناء الفترة الانتقالية. هذه أصعب مشكلة. فكر في حلول مثل استخدام (Change Data Capture – CDC)، أو نشر الأحداث (Event Sourcing)، أو حتى وجود طبقة بيانات مشتركة مؤقتًا.
  • اجعل الواجهة الخانقة ذكية: يمكن للـ Façade أن يفعل أكثر من مجرد التوجيه. يمكنك استخدامه لإضافة مصادقة (Authentication)، أو تسجيل (Logging)، أو حتى اختبار A/B بين الخدمة القديمة والجديدة.

الخلاصة: متى تستخدم نمط الخانق؟

نمط التين الخانق ليس حلاً لكل المشاكل، لكنه سلاح فعال بشكل لا يصدق في الحالات الصحيحة.

استخدمه عندما:

  • لديك نظام مونوليثي ضخم وحيوي (mission-critical) لا يمكنك تحمل مخاطرة إيقافه أو إعادة كتابته بالكامل.
  • تريد تحديث تقنياتك بشكل تدريجي وبأقل مخاطرة ممكنة.
  • تريد الانتقال إلى معمارية الخدمات المصغرة (Microservices) بطريقة منظمة.

تجنبه عندما:

  • التطبيق صغير وبسيط ويمكن إعادة كتابته بسهولة.
  • ليس لديك القدرة على التحكم في تدفق الطلبات (لا يمكنك وضع Façade).

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

أبو عمر

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

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

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

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

آخر المدونات

أدوات وانتاجية

كنت أقضي ساعاتي في كتابة الكود المتكرر: كيف أنقذني ‘المبرمج الزوجي الاصطناعي’ من جحيم إعادة اختراع العجلة؟

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

30 مارس، 2026 قراءة المزيد
نصائح برمجية

الكود الخاص بي كان هرمًا: كيف أنقذتني ‘شروط الحماية’ (Guard Clauses) من جحيم الكود السهمي؟

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

30 مارس، 2026 قراءة المزيد
خوارزميات

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

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

30 مارس، 2026 قراءة المزيد
تسويق رقمي

ميزانيتي التسويقية كانت ثقبًا أسود: كيف أنقذني ‘نموذج الإحالة’ (Attribution Model) من جحيم الإنفاق الأعمى؟

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

30 مارس، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

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

أشارككم تجربتي كـ "أبو عمر"، مبرمج فلسطيني، مع الفوضى البصرية في المشاريع وكيف كان "نظام التصميم" (Design System) هو طوق النجاة. سنتعلم معاً ما هو...

30 مارس، 2026 قراءة المزيد
الشبكات والـ APIs

خدماتي المصغرة كانت كابوسًا: كيف أنقذتني ‘بوابة الواجهات البرمجية’ (API Gateway) من جحيم الفوضى؟

كنت أغرق في بحر من الواجهات البرمجية المكشوفة لخدماتي المصغرة، حتى اكتشفت "بوابة الواجهات البرمجية" (API Gateway). تعالوا أروي لكم كـ "أبو عمر" كيف أعاد...

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

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

أشارككم قصة حقيقية كادت أن تدمر أحد مشاريعي بسبب الاعتماد الكلي على مزود سحابي واحد. سأشرح لكم كيف كانت استراتيجية السحابة المتعددة (Multi-Cloud) طوق النجاة،...

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