تطبيقنا المونوليث كان وحشًا: كيف أنقذنا “نمط التين الخانق” من جحيم التحديث المستحيل؟

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

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

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

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

ما هو “الوحش” المونوليثي؟ ولماذا هو مشكلة؟

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

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

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

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

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

لكن من خبرتي، يا خوي، هذا النهج غالبًا ما يفشل فشلًا ذريعًا، خاصة مع الأنظمة الكبيرة. لماذا؟

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

هنا يأتي دور الحل الأكثر حكمة وعملية.

بطل القصة: نمط التين الخانق (Strangler Fig Pattern)

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

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

  1. التحويل (Transform): نحدد جزءًا من وظائف النظام القديم (مثل إدارة ملفات المستخدمين) ونبني له خدمة جديدة مستقلة (Microservice) باستخدام تقنيات حديثة.
  2. الاعتراض (Intercept): نضع “واجهة” (Façade) أمام النظام القديم، غالبًا ما تكون Reverse Proxy أو API Gateway. هذه الواجهة تعترض الطلبات الواردة. في البداية، تمرر كل الطلبات إلى النظام القديم كالمعتاد.
  3. الخنق (Strangle): نبدأ بتوجيه الطلبات المتعلقة بالوظيفة الجديدة (ملفات المستخدمين) إلى الخدمة الجديدة بدلًا من النظام القديم. ومع الوقت، ننقل المزيد والمزيد من الوظائف إلى خدمات جديدة، ونغير مسار الطلبات إليها، حتى يتم “خنق” النظام القديم بالكامل ويصبح بالإمكان إيقافه وحذفه بأمان.

مثال عملي: كيف بدأنا بخنق “الوحش”

دعونا نأخذ مثالًا عمليًا مشابهًا لما فعلناه. لنفترض أن “الوحش” المونوليثي لديه مسار للوصول لبيانات المستخدم: /api/v1/users/:id.

الخطوة 1: بناء الواجهة (The Façade)

أول شيء فعلناه هو وضع Reverse Proxy مثل Nginx أمام تطبيقنا المونوليثي. لم يلاحظ المستخدمون أي فرق. كل الطلبات كانت تمر عبر Nginx وتصل إلى الوحش.

كان إعداد Nginx بسيطًا جدًا:


# nginx.conf

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

    location / {
        # في البداية، كل الطلبات تذهب إلى النظام القديم
        proxy_pass http://monolith_app:8080;
        proxy_set_header Host $host;
    }
}

هنا، monolith_app:8080 هو عنوان التطبيق القديم.

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

بعد ذلك، قام فريق صغير ببناء خدمة جديدة ومستقلة لإدارة المستخدمين. استخدمنا Node.js وExpress لأنها سريعة ومناسبة لهذا النوع من الخدمات. هذه الخدمة لديها مسار جديد: /api/v2/users/:id.

الكود كان بسيطًا، شيء من هذا القبيل:


// user-service/index.js (مثال مبسط)
const express = require('express');
const app = express();
const port = 3000;

// مسار جديد لجلب بيانات المستخدم من قاعدة بيانات جديدة أو نفس القديمة مؤقتًا
app.get('/api/v2/users/:id', (req, res) => {
    const userId = req.params.id;
    // ... منطق جلب المستخدم من قاعدة البيانات
    const user = { id: userId, name: 'أبو عمر الجديد', email: 'abu.omar.new@example.com' };
    res.json(user);
});

app.listen(port, () => {
    console.log(`User service listening on port ${port}`);
});

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

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


# nginx.conf (النسخة المحدثة)

# تعريف عناوين خدماتنا
upstream monolith_server {
    server monolith_app:8080;
}

upstream user_service_server {
    server user_service_app:3000;
}

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

    # هذا هو الجزء المهم
    # أي طلب يبدأ بـ /api/v1/users سيذهب للخدمة الجديدة
    location /api/v1/users {
        # يمكن إعادة كتابة المسار ليطابق مسار الخدمة الجديدة
        rewrite /api/v1/(.*) /api/v2/$1 break;
        proxy_pass http://user_service_server;
        proxy_set_header Host $host;
    }

    # بقية الطلبات تذهب إلى الوحش القديم
    location / {
        proxy_pass http://monolith_server;
        proxy_set_header Host $host;
    }
}

بهذه الطريقة، أصبح أي طلب لـ my-awesome-app.com/api/v1/users/123 يذهب الآن إلى خدمة المستخدمين الجديدة، بينما طلب مثل my-awesome-app.com/api/v1/invoices لا يزال يذهب إلى المونوليث. لم يتغير شيء بالنسبة لواجهة المستخدم أو للمستخدم النهائي، لكننا في الخلفية بدأنا باستبدال محرك السيارة قطعة قطعة وهي لا تزال تسير!

الخطوة 4: التكرار والتنظيف

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

نصائح أبو عمر الذهبية لتطبيق النمط بنجاح

من خلال تجربتنا، تعلمت بعض الدروس التي أود مشاركتها معكم لتكون رحلتكم أسهل:

  • ابدأ صغيرًا وبسيطًا: لا تحاول خنق جزء معقد من النظام في البداية. اختر وظيفة بسيطة ومعزولة نسبيًا (Read-only API مثلًا) لتثبت نجاح الفكرة وتكسب ثقة الفريق والإدارة.
  • المراقبة والقياس هما عيناك: استثمر بقوة في أدوات المراقبة (Monitoring) والتسجيل (Logging). يجب أن تعرف فورًا أداء الخدمة الجديدة، وهل هناك أخطاء، وكيف يقارن أداؤها بالجزء القديم.
  • استراتيجية قاعدة البيانات: هذه هي أصعب جزئية. في البداية، قد تجعل الخدمة الجديدة تقرأ وتكتب في نفس قاعدة بيانات المونوليث (لتسهيل الأمور). لكن الهدف النهائي هو أن يكون لكل خدمة قاعدة بياناتها الخاصة. هذا يتطلب استراتيجيات لمزامنة البيانات أو نقلها، وهي قصة أخرى طويلة.
  • لا تنسَ التواصل: يجب أن يكون الفريق بأكمله على دراية بالخطة. تقسيم العمل بين فريق “صيانة القديم” وفريق “بناء الجديد” يجب أن يتم بحكمة وتنسيق.
  • استمر في الخنق: بمجرد أن تبدأ، لا تتوقف. الزخم مهم جدًا. كل وظيفة جديدة يتم ترحيلها بنجاح هي انتصار صغير يغذي الحماس للمرحلة التالية.

الخلاصة يا جماعة الخير 🏁

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

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

والله ولي التوفيق.

أبو عمر

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

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

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

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

آخر المدونات

اختبارات الاداء والجودة

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

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

10 أبريل، 2026 قراءة المزيد
ذكاء اصطناعي

بحثنا كان لا يفهم المعنى: كيف أنقذتنا ‘قواعد البيانات المتجهية’ (Vector Databases) من جحيم البحث الحرفي؟

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

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

عملاؤنا المحتملون كانوا أشباحًا: كيف أنقذتنا “نمذجة الإحالة القائمة على البيانات” من جحيم تتبع الإعلانات الأعمى؟

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

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

تطبيقاتنا كانت تستبعد الملايين: كيف أنقذتنا ‘إرشادات الوصول الرقمي’ (WCAG) من جحيم الإقصاء؟

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

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