“يا زلمة، لا تلمس هالكود!”… قصة الوحش الذي صنعته بيدي
أذكر ذلك اليوم جيدًا، كأنه البارحة. كنت جالسًا في مكتبي، فنجان القهوة بالهيل بجانبي، وأمامي شاشة تعرض “تحفتي الفنية” التي بنيتها قبل سنوات: نظام إدارة علاقات عملاء (CRM) ضخم لإحدى الشركات الكبرى. في بداياته، كان هذا النظام مصدر فخري، لكن مع مرور الزمن وتراكم التعديلات والـ “patches” السريعة، تحول إلى وحش متشابك. كود سباغيتي معقد لدرجة أنني، أنا الذي كتبته، أصبحت أخشى الاقتراب منه.
جاءني مدير المشروع بوجه متحمس وقال: “أبو عمر، بدنا نضيف نظام ولاء عملاء جديد مربوط بالذكاء الاصطناعي عشان يقترح منتجات مخصصة!”. ابتسمت ابتسامة صفراء. فكرت في نفسي: “نظام ولاء؟ ذكاء اصطناعي؟ يا زلمة، أنا بخاف أغير لون زر في هالنظام ليروح يضرب كله!”. كانت أي محاولة لإضافة ميزة جديدة تشبه محاولة إجراء عملية جراحية دقيقة في غرفة مظلمة باستخدام مفك براغي.
كانت الخيارات محدودة ومؤلمة:
- إعادة الكتابة الكاملة (The Big Bang Rewrite): مشروع ضخم، مكلف، ومحفوف بالمخاطر. قد يستغرق سنوات، وفي النهاية قد لا يعمل كما هو متوقع.
- البقاء على الوضع الحالي: وهذا يعني الموت البطيء للبيزنس، فالمنافسون يتقدمون ونحن مكانك سر.
كنت في جحيم حقيقي. كيف يمكنني تحديث هذا الوحش دون قتله… أو قتلي؟ هنا، تذكرت نمطًا معماريًا قرأت عنه منذ فترة، اسمه غريب ولكنه عبقري: نمط “التين الخانق” (Strangler Fig Pattern).
ما هو نمط “التين الخانق” (Strangler Fig)؟ وليش اسمه هيك؟
الاسم مستوحى من شجرة التين الخانق في الغابات الاستوائية. هذه الشجرة تبدأ حياتها كبذرة صغيرة على أغصان شجرة قديمة ضخمة. مع الوقت، تنزل جذورها إلى الأرض وتبدأ بالنمو حول الشجرة المضيفة، وتتشابك معها وتعتمد عليها. شيئًا فشيئًا، تصبح نبتة التين قوية جدًا وتنمو لتشكل هيكلًا جديدًا حول الشجرة القديمة. في النهاية، تموت الشجرة الأصلية وتتحلل، وتبقى شجرة التين الخانق مكانها، قوية وشامخة، وقد أخذت شكل الشجرة القديمة ووظيفتها.
في عالم البرمجيات، الفكرة مماثلة تمامًا. بدلًا من إعادة كتابة النظام القديم (Monolith) دفعة واحدة، نقوم ببناء نظام جديد (مجموعة من الخدمات المصغرة أو Microservices) “حول” النظام القديم. نبدأ بتوجيه أجزاء من الطلبات (Traffic) إلى الخدمات الجديدة تدريجيًا. مع مرور الوقت، تستحوذ الخدمات الجديدة على المزيد والمزيد من وظائف النظام القديم، حتى يصبح النظام القديم فارغًا من الداخل ويمكن إيقافه بأمان.
كيف طبقنا “التين الخانق” على أرض الواقع: خطوات عملية
بعد إقناع الإدارة بالفكرة، بدأنا رحلتنا لتطبيق هذا النمط. كانت الخطة واضحة ومقسمة إلى مراحل صغيرة وآمنة.
الخطوة الأولى: بناء “الواجهة الخانقة” (The Strangler Façade)
هذه هي أهم خطوة على الإطلاق. الفكرة هي وضع طبقة جديدة (Proxy أو API Gateway) أمام النظام القديم. من هذه اللحظة، يجب أن تمر جميع الطلبات القادمة من المستخدمين أو الأنظمة الأخرى عبر هذه الواجهة. هذه الواجهة في البداية لا تفعل شيئًا سوى تمرير كل الطلبات كما هي إلى النظام القديم.
هذه الواجهة هي التي ستمكننا لاحقًا من “خنق” النظام القديم وتوجيه الطلبات إلى الخدمات الجديدة.
نصيحة أبو عمر: يا جماعة الخير، لا تستهينوا بهذه الخطوة. إذا لم تسيطروا على كل نقاط الدخول للنظام، سيفشل النمط كله. هذه الواجهة هي “عنق الزجاجة” الذي ستتحكمون من خلاله بكل شيء. استخدمنا في مشروعنا Nginx كـ Reverse Proxy، ولكن يمكنك استخدام أي تقنية مشابهة مثل Express.js Gateway أو خدمات سحابية مثل AWS API Gateway.
// مثال بسيط لواجهة خانقة باستخدام Express.js و http-proxy-middleware
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
// عنوان الوحش القديم (النظام المونوليثي)
const LEGACY_SYSTEM_URL = 'http://api.legacy-crm.com';
// في البداية، الواجهة تمرر كل شيء للنظام القديم
app.use('/', createProxyMiddleware({
target: LEGACY_SYSTEM_URL,
changeOrigin: true,
}));
app.listen(80, () => {
console.log('Strangler Façade is running on port 80...');
});
الخطوة الثانية: تحديد أول ضحية (أول ميزة للتحديث)
الآن بعد أن أصبح لدينا سيطرة على تدفق الطلبات، حان وقت اختيار أول جزء من النظام لنقوم باستبداله. القاعدة الذهبية هنا: ابدأ بشيء صغير ومنعزل نسبيًا.
في حالتنا، قررنا أن نبدأ بصفحة “إدارة ملفات المستخدمين” (User Profile Management). لماذا؟
- كانت منطقة نقوم بتحديثها كثيرًا.
- منطقها كان واضحًا ومفهومًا.
- كانت منفصلة نسبيًا عن باقي أجزاء النظام المعقدة مثل الفواتير والتقارير.
نصيحة أبو عمر: “لقمة لقمة بتشبع”. لا تكن طماعًا وتحاول استبدال جزء ضخم من النظام في البداية. اختر معركة صغيرة يمكنك الفوز بها بسهولة. هذا سيعطيك ويعطي فريقك دفعة معنوية وثقة، وسيُظهر للإدارة قيمة هذا النهج بسرعة.
الخطوة الثالثة: الخنق والتحويل (Strangle and Redirect)
هنا يبدأ السحر. قمنا ببناء خدمة مصغرة (Microservice) جديدة تمامًا باستخدام تقنيات حديثة (Node.js وฐาน بيانات MongoDB) لتتولى مسؤولية إدارة ملفات المستخدمين. بعد أن أصبحت الخدمة الجديدة جاهزة، عدنا إلى “الواجهة الخانقة” وقمنا بتعديل بسيط على إعداداتها.
الآن، أي طلب يأتي إلى المسار /api/users يتم توجيهه إلى الخدمة الجديدة، بينما كل الطلبات الأخرى (مثل /api/invoices أو /api/reports) لا تزال تذهب إلى النظام القديم.
// ... إعدادات الواجهة السابقة
const NEW_USERS_SERVICE_URL = 'http://users-service:3000'; // عنوان الخدمة المصغرة الجديدة
// 1. الخنق: اعتراض طلبات المستخدمين وتوجيهها للخدمة الجديدة
app.use('/api/users', createProxyMiddleware({
target: NEW_USERS_SERVICE_URL,
changeOrigin: true,
}));
// 2. التحويل: باقي الطلبات لا تزال تذهب للنظام القديم
app.use('/', createProxyMiddleware({
target: LEGACY_SYSTEM_URL,
changeOrigin: true,
}));
// ...
النتيجة؟ أصبح لدينا جزء من النظام يعمل بتقنيات حديثة، يمكن نشره وتحديثه بشكل مستقل، وكل ذلك دون المساس بالوحش القديم. المستخدمون لم يشعروا بأي فرق، ولكننا من الداخل كنا قد بدأنا عملية التحرير.
الخطوة الرابعة: التكرار حتى موت الوحش (Rinse and Repeat)
الآن، العملية أصبحت واضحة. نكرر الخطوات السابقة مرارًا وتكرارًا:
- اختر ميزة أخرى (مثل نظام المنتجات).
- ابنِ لها خدمة مصغرة جديدة.
- حدّث الواجهة الخانقة لتوجيه الطلبات لها.
مع كل دورة، يتقلص دور النظام القديم وتزيد قوة النظام الجديد. مثل شجرة التين الخانق، ينمو نظامنا الجديد ويخنق القديم ببطء ولكن بثبات، حتى يأتي اليوم الذي نجد فيه أن النظام القديم لا يستقبل أي طلبات على الإطلاق. في تلك اللحظة، وبكل ثقة، يمكننا إطفاء خوادمه والاحتفال بموته.
تحديات ونصائح من قلب المعركة
الطريق لم يكن مفروشًا بالورود، وواجهتنا بعض التحديات الصعبة.
- تكامل قواعد البيانات: هذا هو “مربط الفرس” وأصعب جزء. كيف تتعامل الخدمة الجديدة مع البيانات الموجودة في قاعدة بيانات النظام القديم؟ في البداية، سمحنا للخدمة الجديدة بالقراءة مباشرة من قاعدة بيانات القديمة (Read-Only). لكن على المدى الطويل، هذا يخلق تبعية سيئة. الحل الأفضل كان استخدام تقنيات مزامنة البيانات مثل (Change Data Capture – CDC) أو بناء طبقة API فوق قاعدة البيانات القديمة لتكون مصدر البيانات الوحيد.
- الاتساق بين الأنظمة (Consistency): ماذا لو كانت عملية ما تتطلب تحديث بيانات في النظام القديم والجديد معًا (مثل إنشاء طلبية جديدة)؟ هنا تظهر تعقيدات مثل نمط “Saga” لإدارة المعاملات الموزعة. كن مستعدًا لهذه التحديات.
- الثقافة والعقلية: إقناع الفريق والإدارة بأن هذا النهج التدريجي أفضل من “الثورة” الكبرى كان تحديًا بحد ذاته. عرض النتائج السريعة والنجاحات الصغيرة كان أفضل وسيلة لإثبات وجهة نظرنا.
الخلاصة: التين الخانق ليس مجرد نمط، بل هو فلسفة! 🪴
في النهاية، نمط “التين الخانق” أنقذنا من ورطة حقيقية. لقد سمح لنا بتحديث نظامنا الضخم والمعقد بطريقة آمنة وتدريجية، مع تقديم قيمة للعمل بشكل مستمر.
هذا النمط هو أكثر من مجرد تقنية؛ إنه فلسفة في التطوير. فلسفة تفضل التطور التدريجي على الثورات الخطرة، والتحسين المستمر على الانتظار الطويل. إذا كنت تواجه وحشًا برمجيًا قديمًا في عملك، فلا تخف منه. ابدأ بزراعة بذرة “التين الخانق” الصغيرة، وشاهدها وهي تنمو لتخنق المستحيل وتمنحك نظامًا جديدًا يمكنك أن تفخر به من جديد.