أذكرها وكأنها البارحة. كانت ليلة هادئة في المكتب، وأنا أستمتع بفنجان القهوة السادة الذي لا يفارقني، أضع اللمسات الأخيرة على ميزة جديدة. فجأة، اهتز هدوء الليل الكاذب برنين هواتف الفريق كأنه إنذار حريق. النظام المالي المركزي، ذلك “الختيار” الذي ورثناه عن الأجيال السابقة من المبرمجين، قد توقف عن العمل تماماً في منتصف عمليات الإغلاق الشهري.
تجمّعنا حوله، ننظر إلى شاشات الأخطاء المبهمة كأننا ننظر في طلاسم قديمة. كان هذا النظام وحشاً بكل ما للكلمة من معنى؛ مكتوب بلغة برمجية لم يعد أحد يتقنها، بقاعدة بيانات لا يجرؤ أحد على لمس مخططها، وبدون أي توثيق يُذكر. كل محاولة لإصلاح خطأ كانت كالمشي في حقل ألغام، وكل تغيير بسيط كان يهدد بانهيار أجزاء أخرى لا علاقة لها. قال أحد الزملاء الجدد بحماس: “يا جماعة، لازم نعيد كتابته من الصفر!”. نظرنا إليه نظرة الأب الذي يسمع ابنه يقول إنه سيصبح رائد فضاء وهو يخاف من المرتفعات. كانت فكرة “إعادة الكتابة الكبرى” هي الكابوس الأكبر الذي يطاردنا جميعاً.
في تلك الليلة، وبعد ساعات من الترقيع والحلول المؤقتة، عاد النظام للعمل بصعوبة. لكن البذرة كانت قد زُرعت في رأسي. لا يمكننا الاستمرار هكذا. يجب أن يكون هناك طريق ثالث، طريق بين “الموت البطيء مع النظام القديم” و”الانتحار بمشروع إعادة كتابة كامل”. وهنا بدأت رحلتي مع ما يُعرف بـ “نمط التين الخانق”.
لماذا “إعادة الكتابة الكبرى” هي فخ مميت؟
قبل أن نغوص في الحل، دعونا نتفق على سبب كون فكرة “يلا نهد المعبد ونبنيه من جديد” فكرة سيئة في 99% من الحالات. من خبرتي، هذه هي الأسباب الرئيسية:
- مخاطرة هائلة: أنت توقف تطوير أي ميزات جديدة لشهور أو حتى سنوات، وتضع كل رهانات الشركة على مشروع واحد ضخم. أي خطأ في التقدير يمكن أن يكون قاتلاً.
- الوقت الطويل للقيمة (Time to Value): لن يرى العميل أو الشركة أي فائدة إلا بعد انتهاء المشروع بالكامل، وهذا قد يستغرق وقتاً طويلاً جداً. في عالم الأعمال السريع، هذا ترف لا نملكه.
- نسيان منطق العمل الخفي: الأنظمة القديمة مليئة بمنطق عمل وقواعد “غير مكتوبة” تراكمت عبر السنين. إعادة كتابتها من الصفر تعني أنك ستفقد الكثير من هذه التفاصيل الدقيقة، ولن تكتشفها إلا بعد فوات الأوان.
- تثبيط همة الفريق: العمل على مشروع طويل الأمد بدون تحقيق إنجازات ملموسة هو وصفة أكيدة لإحباط المطورين وتشتيتهم.
ببساطة، إعادة الكتابة الكبرى هي محاولة لعبور وادٍ سحيق بقفزة واحدة. الأغلب سيسقط في المنتصف.
شجرة التين الخانق: الحل المستوحى من الطبيعة
في إحدى رحلاتي الفكرية على الإنترنت، صادفت مقالة للخبير الأسطوري مارتن فاولر يتحدث فيها عن “نمط التين الخانق” (Strangler Fig Pattern). الاسم غريب، لكن الفكرة عبقرية ومستوحاة من الطبيعة.
شجرة التين الخانق هي نبتة تبدأ حياتها بالنمو على أغصان شجرة قديمة ضخمة. مع الوقت، تُنزل جذورها إلى الأرض وتنمو وتلتف حول الشجرة المضيفة، وتتنافس معها على الضوء والموارد. شيئاً فشيئاً، تصبح النبتة الجديدة هي المهيمنة، وتتحلل الشجرة القديمة الأصلية بداخلها، تاركةً وراءها شجرة التين القوية مكانها. لا أحد “يقتلع” الشجرة القديمة، بل يتم استبدالها تدريجياً وبشكل عضوي.
كيف نطبق هذا في عالم البرمجيات؟
الفكرة هي أن نبني نظامنا الجديد حول النظام القديم، وليس بدلاً منه دفعة واحدة. نحن نخنق النظام القديم ببطء، قطعة تلو الأخرى، حتى لا يتبقى منه شيء. وهذا يتم عبر خطوات عملية ومنظمة.
خطوات “خنق” النظام القديم: دليل عملي
هذه هي الخطة التي اتبعناها بالضبط لترويض وحشنا القديم، والتي يمكنك تطبيقها على أي نظام “مونوليث” تعاني منه.
الخطوة 1: بناء “الواجهة الوكيلة” (The Facade)
هذه هي أهم خطوة. يجب أن نضع “بوابة” أمام النظام القديم. هذه البوابة، التي نسميها الواجهة أو البروكسي (Proxy/Facade)، ستكون نقطة الدخول الوحيدة لكل الطلبات الموجهة للنظام. في البداية، كل ما تفعله هذه الواجهة هو تمرير الطلبات كما هي إلى النظام القديم وإعادة الاستجابة.
الهدف هو السيطرة على تدفق الطلبات. من يسيطر على الطريق، يسيطر على المدينة. هذه الواجهة هي سيطرتنا على الطريق المؤدي إلى النظام القديم.
نصيحة أبو عمر: لا تعقّد هذه الواجهة. يمكن أن تكون بسيطة جداً مثل Nginx, HAProxy, أو حتى تطبيق ويب خفيف (Node.js/Express, Python/Flask). الهدف هو التحكم بالمسار (Routing) وليس إضافة منطق معقد.
الخطوة 2: تحديد واستهداف أول “غصن”
الآن بعد أن أصبح لدينا بوابة، حان وقت اختيار أول قطعة من النظام القديم لنستبدلها. لا تكن طموحاً جداً. اختر شيئاً:
- منعزلاً نسبياً: وحدة لا تعتمد عليها أجزاء كثيرة أخرى من النظام.
- مفيداً وواضحاً: شيء يمكن لفريق المنتج والعمل رؤية قيمته بسرعة.
- قليل المخاطر: ربما صفحة لعرض المعلومات (Read-only) بدلاً من عملية دفع معقدة.
في حالتنا، اخترنا وحدة إدارة ملفات المستخدمين. كانت عملية بسيطة نسبياً ولا تؤثر على المنطق المالي الأساسي.
الخطوة 3: بناء الخدمة الجديدة وتوجيه الطلبات
قمنا ببناء خدمة مصغّرة (Microservice) جديدة تماماً، باستخدام أحدث التقنيات التي نحبها (في حالتنا كانت Go)، تقوم بنفس وظيفة إدارة المستخدمين في النظام القديم. بعد أن أصبحت جاهزة ومختبرة، حان وقت السحر.
عدنا إلى “الواجهة الوكيلة” وقمنا بتعديل بسيط في إعداداتها. الآن، أي طلب يأتي على المسار /api/users/... يتم توجيهه إلى الخدمة الجديدة، بينما كل الطلبات الأخرى ما زالت تذهب إلى النظام القديم “الختيار”.
هذا مثال بسيط جداً لكيف يمكن أن يبدو هذا المنطق في واجهة وكيلة مبنية بـ Express.js (Node.js):
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const LEGACY_SYSTEM_URL = 'http://legacy-beast:8080';
const NEW_USERS_SERVICE_URL = 'http://new-users-service:3000';
// هذا هو "الخانق"
// أي طلب يبدأ بـ /api/users يذهب للخدمة الجديدة
app.use('/api/users', createProxyMiddleware({
target: NEW_USERS_SERVICE_URL,
changeOrigin: true,
pathRewrite: {
'^/api/users': '/', // أعد كتابة المسار ليتناسب مع الخدمة الجديدة
},
}));
// أي شيء آخر، مرره للنظام القديم "الختيار"
app.use('/', createProxyMiddleware({
target: LEGACY_SYSTEM_URL,
changeOrigin: true
}));
app.listen(80, () => {
console.log('Strangler Facade is running on port 80');
});
بهذه البساطة، بدأنا عملية الخنق. المستخدم النهائي لم يشعر بأي شيء، لكننا في الخلفية كنا قد استبدلنا أول قطعة بنجاح.
الخطوة 4: التكرار، ثم التكرار، ثم التكرار (Rinse and Repeat)
هنا يكمن جمال النمط. بعد نجاح الخطوة الأولى، احتفلنا قليلاً (شربنا الشاي بالنعناع هذه المرة بدلاً من القهوة)، ثم كررنا العملية.
- اختر الوظيفة التالية (مثلاً، تقارير المبيعات).
- ابنِ خدمة مصغرة جديدة لها.
- حدّث الواجهة الوكيلة لتوجيه الطلبات
/api/reportsللخدمة الجديدة. - اختر الوظيفة التي تليها… وهكذا.
مع كل تكرار، كانت الخدمة الجديدة تنمو وتتوسع، والنظام القديم يتقلص ويضمر. كنا نخنقه ببطء ولكن بثبات.
الخطوة 5: إعلان وفاة “الختيار”
بعد شهور من العمل الممنهج، وصلنا إلى اللحظة الحاسمة. آخر وظيفة في النظام القديم تم نقلها إلى خدمة جديدة. الواجهة الوكيلة لم تعد توجّه أي طلبات إلى النظام القديم. كل شيء يذهب إلى الخدمات الجديدة.
في ذلك اليوم، عقدنا اجتماعاً قصيراً. لم يكن هناك احتفال صاخب، بل شعور عميق بالرضا والراحة. فتحنا صفحة مراقبة الخوادم، وبنقرة زر واحدة، أوقفنا الخادم الذي يستضيف النظام القديم إلى الأبد. لقد مات الوحش، وتحللت الشجرة القديمة، وبقيت الغابة الجديدة القوية مكانها.
الخلاصة… وزبدة الحكي
نمط التين الخانق ليس مجرد نمط معماري، بل هو فلسفة في إدارة التغيير والتعامل مع التعقيد. إنه يعلمنا أن أكبر المشاكل يمكن حلها ليس بمواجهتها مباشرة، بل بالالتفاف حولها وتفكيكها قطعة قطعة.
إذا كنت تواجه نظاماً قديماً يبدو من المستحيل المساس به، لا تستسلم لفكرة “إعادة الكتابة الكبرى” المدمرة. تذكر قصة شجرة التين:
- تحكّم بالمدخل: ابنِ واجهة وكيلة (Facade).
- ابدأ صغيراً: اختر قطعة سهلة وابنِ بديلاً لها.
- وجّه تدريجياً: استخدم الواجهة لتوجيه جزء من الطلبات للبديل الجديد.
- كرّر العملية: استمر في “خنق” النظام القديم وظيفة تلو الأخرى.
- احتفل بالنصر: في النهاية، ستجد أنك بنيت نظاماً جديداً بالكامل دون أن يشعر أحد ودون أن توقف عجلة العمل.
إنها رحلة طويلة، ولكنها رحلة آمنة ومجزية، وتحافظ على سلامة عقلك وفريقك. الشغلانة مش مزحة، بس مع التخطيط الصح، كل وحش يمكن ترويضه. 👍