كان المونوليث يلتهمنا أحياء: كيف أنقذنا نمط الخانق (Strangler Fig) من جحيم إعادة الكتابة الأبدية؟

“يا جماعة، النظام بموت… وإحنا معه”

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

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

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

ساد صمت ثقيل. كان كلامي منطقياً لكنه محبط. فما الحل إذن؟ هل نبقى أسرى هذا الوحش؟ في تلك الليلة، وأنا أبحث عن حلول، وقعت عيناي على مقال لمارتن فاولر يتحدث عن نمط معماري غريب اسمه “نمط شجرة التين الخانقة” (Strangler Fig Pattern). الفكرة كانت بسيطة وعبقرية في آن واحد، ومستوحاة من الطبيعة. هنا بدأت رحلة إنقاذنا.

ما هو المونوليث؟ ولماذا يصبح كابوساً؟

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

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

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

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

فكرة “إعادة الكتابة الكاملة”: الحلم الذي يتحول إلى جحيم

عندما يصل المونوليث إلى مرحلة الألم، يكون رد الفعل الطبيعي هو “لنرمِ كل هذا في القمامة ونبدأ من جديد”. هذا ما يسمى بـ “The Big Rewrite”. يبدو الأمر مغرياً، لكنه من أخطر القرارات التي يمكن أن تتخذها شركة تقنية. لماذا؟

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

وهنا يأتي المنقذ: نمط الخانق (Strangler Fig Pattern) 🌳

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

في عالم البرمجيات، الفكرة مماثلة:

  1. لا تلمس النظام القديم (المونوليث). دعه يعمل كما هو.
  2. ابنِ “واجهة فاصلة” (Façade) أمام النظام القديم. هذه الواجهة هي التي ستستقبل كل الطلبات من المستخدمين. في البداية، كل ما تفعله هو تمرير الطلبات كما هي إلى المونوليث.
  3. حدد جزءاً من النظام (مثلاً، إدارة ملفات المستخدمين) وقم ببنائه من جديد كخدمة مستقلة (Microservice) حديثة.
  4. عدّل الواجهة الفاصلة لتوجه الطلبات المتعلقة بملفات المستخدمين إلى الخدمة الجديدة، بينما بقية الطلبات لا تزال تذهب إلى المونوليث.
  5. كرر العملية: اختر جزءاً آخر، ابنِ الخدمة الجديدة، حدث الواجهة. وهكذا دواليك.

مع مرور الوقت، يتم “خنق” المونوليث تدريجياً، حيث تنتقل وظائفه واحدة تلو الأخرى إلى خدمات جديدة، حتى يصبح فارغاً ويمكن إيقافه بأمان.

كيف طبقنا نمط الخانق خطوة بخطوة؟

هذا هو الجزء العملي. إليكم كيف فعلناها بالضبط في مشروعنا:

الخطوة الأولى: بناء الواجهة الفاصلة (The Façade)

كانت هذه أهم خطوة. قررنا استخدام API Gateway ليكون هو الواجهة الفاصلة. يمكنك استخدام أي تقنية تعمل كـ Reverse Proxy مثل Nginx, Traefik, أو خدمات API Gateway السحابية. الهدف هو وضع طبقة تحكم بين المستخدمين ونظامنا.

في البداية، كان الإعداد بسيطاً جداً. كل الطلبات التي تأتي على api.our-shop.com يتم توجيهها إلى المونوليث القديم.

# مثال بسيط باستخدام Nginx
server {
    listen 80;
    server_name api.our-shop.com;

    location / {
        # في البداية، كل شيء يذهب للمونوليث
        proxy_pass http://monolith_app:8080;
        proxy_set_header Host $host;
    }
}

الخطوة الثانية: اختيار أول قطعة “لخنقها”

كان النقاش حامياً حول أول ميزة نبدأ بها. القاعدة الذهبية هي: ابدأ بشيء له حدود واضحة (well-defined boundaries) ويوفر قيمة ملموسة لكنه ليس الجزء الأكثر خطورة في النظام.

وقع اختيارنا على “قائمة أمنيات المستخدم” (User Wishlist). كانت ميزة مستقلة نسبياً، والبيانات الخاصة بها ليست معقدة.

الخطوة الثالثة: بناء الخدمة الجديدة وتوجيه الطلبات

قمنا ببناء خدمة مصغرة جديدة باستخدام Node.js و قاعدة بيانات MongoDB (كنا نريد تجربة NoSQL). بعد أن أصبحت الخدمة جاهزة، قمنا بتعديل إعدادات الـ Nginx.

# Nginx بعد إضافة الخدمة الجديدة
server {
    listen 80;
    server_name api.our-shop.com;

    # الطلبات الخاصة بقائمة الأمنيات تذهب للخدمة الجديدة
    location /api/wishlist/ {
        proxy_pass http://wishlist_service:3000/;
        proxy_set_header Host $host;
    }

    # كل شيء آخر لا يزال يذهب للمونوليث
    location / {
        proxy_pass http://monolith_app:8080;
        proxy_set_header Host $host;
    }
}

بمجرد تطبيق هذا الإعداد، أصبحت كل الطلبات التي تبدأ بـ /api/wishlist/ تذهب إلى خدمتنا الجديدة اللامعة، بينما استمر المونوليث في التعامل مع كل شيء آخر. لم يشعر المستخدم بأي فرق، لكننا في الخلفية كنا قد بدأنا عملية الخنق! 🚀

الخطوة الرابعة: التكامل مع المونوليث

هنا يكمن التحدي الأكبر. خدمتنا الجديدة (Wishlist) كانت تحتاج إلى معرفة معلومات عن المستخدم (User ID, Name). كيف تحصل عليها؟ كان أمامنا عدة خيارات:

  • استدعاء API على المونوليث: لحسن الحظ، كان المونوليث لديه API داخلية للحصول على بيانات المستخدم. خدمتنا الجديدة كانت تستدعي هذه الـ API. هذا هو الخيار الأنظف.
  • مشاركة قاعدة البيانات (قراءة فقط): هذا حل خطير وكنا نتجنبه، لكنه خيار مطروح. تسمح للخدمة الجديدة بالقراءة مباشرة من جداول المستخدمين في قاعدة بيانات المونوليث. إنه يسبب اقتراناً قوياً (tight coupling) لكنه قد يكون حلاً مؤقتاً.
  • مزامنة البيانات عبر الأحداث (Event-Driven): هذا هو الحل الأمثل على المدى الطويل. عندما يتم تحديث مستخدم في المونوليث، يقوم المونوليث بإصدار “حدث” (Event) مثل UserUpdated. تلتقط الخدمة الجديدة هذا الحدث وتحدث نسختها المحلية من بيانات المستخدم.

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

الخطوة الخامسة: التكرار والخنق التدريجي

بعد نجاح أول خدمة، ارتفعت معنويات الفريق. كررنا العملية:

  1. اخترنا الميزة التالية: “مراجعات المنتجات”.
  2. بنينا خدمة المراجعات.
  3. حدثنا الواجهة الفاصلة (Nginx).
  4. قمنا بمزامنة بيانات المنتجات والمستخدمين التي تحتاجها خدمة المراجعات.
  5. ثم انتقلنا إلى سلة التسوق… ثم إلى الكتالوج… وهكذا.

مع كل خدمة جديدة، كان الوحش المونوليثي يتقلص. كنا “نخنق” وظائفه قطعة قطعة. وبعد حوالي 18 شهراً، جاء اليوم الذي احتفلنا فيه بإيقاف آخر جزء من المونوليث. لقد مات الوحش، وبقيت حديقة من الخدمات المصغرة الحديثة والقابلة للصيانة مكانه. 🎉

الخلاصة: اخنق المونوليث، لا تدعه يخنقك! 💪

نمط الخانق ليس حلاً سحرياً سريعاً، بل هو استراتيجية طويلة الأمد. إنه ماراثون وليس سباق سرعة. لكنه يوفر مساراً آمناً وعملياً لتحديث الأنظمة القديمة دون المخاطرة الهائلة التي تأتي مع “إعادة الكتابة الكاملة”.

الفوائد التي جنيناها كانت هائلة:

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

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

أبو عمر

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

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

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

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

آخر المدونات

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

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

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

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

كنا ندفع ثمن الخوادم حتى وهي نائمة: كيف حررتنا الحوسبة بدون خوادم (Serverless) من جحيم التكاليف الخاملة؟

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

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

كانت قاعدة بياناتنا تتوسل الرحمة: كيف أنقذتنا استراتيجية التخزين المؤقت الجانبي (Cache-Aside) من جحيم الاستعلامات؟

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

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