يا جماعة الخير، السلام عليكم ورحمة الله.
اسمحوا لي أبدأ معكم بحكاية صارت معي قبل كم سنة، حكاية بتلخص كابوس كل مبرمج. كانت ليلة خميس، والكل بستنى يروّح على الدار ويرتاح بعد أسبوع شغل طويل. كان عنا ميزة جديدة، تبدو بسيطة على الورق، وهي عبارة عن نظام توصيات جديد للمستخدمين في منصتنا. قضينا أسابيع نطور فيها، والاختبارات كلها تمام التمام على بيئة التجربة (Staging).
قررنا نطلقها الساعة 10 بالليل، “عشان يكون ضغط المستخدمين خفيف”، هيك قلنا لحالنا. ضغطنا زر النشر (Deploy)، وراقبنا الشاشات. أول دقيقة، كل شي هادي. ثاني دقيقة، بلشت توصلنا تنبيهات. مؤشر استخدام المعالج (CPU) لقواعد البيانات نط للـ 100% وثبت هناك! الموقع صار بطيئاً لدرجة شلل الأطفال، وبعدها وقع بالكامل.
بلشت التلفونات ترن، والمدير التقني صوته على الخط معصب، والضغط النفسي وصل حده. قضينا الساعتين اللي بعدهم في عملية “إرجاع” (Rollback) مذلة ومعقدة، نحاول نرجع الكود القديم ونصلح المصيبة اللي صارت. ضاع ليل الخميس، وضاعت معه أعصابنا. وقتها قلت لحالي: “أكيد في طريقة أفضل من هيك! مش معقول كل إطلاق ميزة جديدة يكون مغامرة حياة أو موت”.
وهون يا جماعة، بدأت رحلتي مع مفهوم بسيط لكن عبقري، غيّر طريقة تفكيرنا وعملنا بالكامل: أعلام الميزات (Feature Flags).
ما هي أعلام الميزات (Feature Flags) وشو قصتها؟
ببساطة، أعلام الميزات هي تقنية بتسمحلك تشغّل أو تطفّي أجزاء من الكود البرمجي بدون ما تحتاج تعمل عملية نشر (Deploy) جديدة. تخيلها زي مفتاح الكهربا في بيتك. بتقدر تركّب لمبة جديدة في السقف (تنشر الكود)، بس اللمبة ما رح تضوي (الميزة ما رح تظهر للمستخدم) إلا لما تكبس على المفتاح (تفعّل العلم).
تعريف بسيط لغير التقنيين
فكر فيها كالتالي: أنت تبني بيتاً جديداً. بدلاً من أن تفتح كل الغرف لكل الناس فور انتهاء البناء، تضع قفلاً على باب كل غرفة. يمكنك أن تعطي المفتاح لزوجتك لتجرب غرفة النوم، ولأولادك ليجربوا غرفتهم، ولبعض الأصدقاء المقربين ليجربوا غرفة الضيوف. أنت تتحكم بمن يدخل وأين ومتى، بينما بقية البيت يبقى مغلقاً. هذا بالضبط ما تفعله أعلام الميزات لتطبيقك.
التعريف التقني (للمهتمين)
من الناحية التقنية، علم الميزات هو في أبسط صوره جملة شرطية if/else تحيط بالكود الخاص بالميزة الجديدة. القيمة اللي بتحكم الشرط (صح أو خطأ / true or false) ما بتكون ثابتة في الكود، بل يتم جلبها من مصدر خارجي وقت التشغيل (runtime).
// مثال بسيط بلغة JavaScript
if (featureIsEnabled('new-user-profile-page')) {
// اعرض صفحة المستخدم الجديدة
showNewUserProfile();
} else {
// اعرض الصفحة القديمة
showOldUserProfile();
}
الدالة featureIsEnabled هي قلب الموضوع. هي اللي بتروح بتسأل “هل علم ‘new-user-profile-page’ شغال؟”. الإجابة ممكن تكون مخزنة في ملف إعدادات، في قاعدة بيانات، أو في خدمة متخصصة لإدارة الأعلام.
كيف غيرت أعلام الميزات طريقة عملنا؟ الفوائد العملية
بعد ما تبنينا هذي الفكرة، تغيرت حياتنا من جحيم ليالي الخميس إلى عمليات نشر هادئة ومملة (وهذا شيء جيد جداً في عالمنا!). إليكم كيف:
1. فصل النشر (Deployment) عن الإطلاق (Release)
هذه هي الفائدة الأعظم. قبل أعلام الميزات، كان النشر والإطلاق شيئاً واحداً. تضغط زر النشر، والميزة تظهر فوراً لكل المستخدمين. هذا هو “الإطلاق المتفجر” (Big Bang Release) المحفوف بالمخاطر.
مع أعلام الميزات، أصبحنا ننشر الكود الجديد على بيئة الإنتاج وهو “مطفأ” أو “مخفي”. عملية النشر أصبحت حدثاً تقنياً بحتاً ومنخفض المخاطر. أما قرار “الإطلاق”، أي تفعيل الميزة للمستخدمين، فأصبح قرار عمل (Business Decision) يمكن اتخاذه في أي وقت وبكبسة زر، بدون الحاجة لأي مبرمج.
2. اختبار الميزات في بيئة الإنتاج الحقيقية (Testing in Production)
قد يبدو هذا المصطلح مرعباً، لكن مع الأعلام يصبح آمناً وقوياً جداً. بدلاً من محاولة محاكاة بيئة الإنتاج المعقدة، يمكنك اختبار الميزة الجديدة على البيئة الحقيقية ولكن لمجموعة محدودة جداً من المستخدمين.
نصيحة من أبو عمر: ابدأ بتفعيل الميزة لفريقك الداخلي فقط. استخدم معرفات المستخدمين (User IDs) الخاصة بفريق التطوير وفريق ضمان الجودة (QA) ومدير المنتج. دعهم يستخدمون الميزة في سياقها الحقيقي لأيام. هذا يكشف عن مشاكل لا يمكن لأي بيئة اختبار أن تكشفها.
هذا ما يسمى “Canary Release”. إذا اكتشفنا أي مشكلة، مثل ارتفاع استخدام المعالج في قصتنا الأولى، كل ما علينا فعله هو إطفاء العلم. لا حاجة لعملية إرجاع (rollback) طارئة ومعقدة.
3. الإطلاق التدريجي (Progressive Delivery) و A/B Testing
بعد التأكد من أن الميزة مستقرة مع الفريق الداخلي، يمكنك البدء في إطلاقها تدريجياً لنسبة صغيرة من المستخدمين الحقيقيين. مثلاً:
- اليوم الأول: تفعيل الميزة لـ 1% من المستخدمين.
- اليوم الثاني: مراقبة الأداء والمقاييس. كل شيء تمام؟ نرفع النسبة إلى 10%.
- اليوم الثالث: الأمور ممتازة؟ نرفعها إلى 50%.
- نهاية الأسبوع: تفعيل الميزة لـ 100% من المستخدمين.
هذا يقلل من تأثير أي مشكلة غير متوقعة. بدلاً من أن تؤثر على كل المستخدمين، ستؤثر على نسبة صغيرة جداً ويمكن احتواؤها بسرعة. كما يمكنك استخدام هذه التقنية لعمل اختبارات A/B، حيث تعرض نسختين مختلفتين من الميزة لمجموعتين من المستخدمين وترى أيهما تحقق نتائج أفضل.
4. مفتاح الإيقاف الفوري (Kill Switch)
هذا هو المنقذ في حالات الطوارئ. تخيل أن الميزة الجديدة تسببت في بطء شديد بعد إطلاقها لـ 50% من المستخدمين. بدلاً من حالة الذعر التي عشناها في قصتي، يمكنك بكل هدوء الدخول إلى لوحة التحكم الخاصة بأعلام الميزات وإطفاء العلم. في غضون ثوانٍ، ستختفي الميزة ويعود النظام إلى حالته المستقرة، كل هذا بدون أي تدخل برمجي أو عملية نشر جديدة.
لنطبق عملياً: كيف تبدأ مع أعلام الميزات؟
الأمر أسهل مما تتخيل، ويمكنك البدء بخطوات بسيطة.
الطريقة البسيطة: ملف الإعدادات (Configuration File)
للبدايات، لا تحتاج لأي أدوات معقدة. يمكنك ببساطة إنشاء ملف JSON في مشروعك يحتوي على أعلام الميزات.
ملف features.json:
{
"enable-new-dashboard": true,
"show-beta-warning": false,
"new-checkout-flow-percentage": 10
}
ثم في الكود الخاص بك (مثال بـ Node.js):
const features = require('./features.json');
function isFeatureEnabled(featureName) {
return features[featureName] === true;
}
if (isFeatureEnabled('enable-new-dashboard')) {
// ... اعرض الداشبورد الجديد
}
العيب: هذه الطريقة ليست ديناميكية. لتغيير قيمة العلم، تحتاج إلى تعديل الملف ونشر الكود من جديد، وهذا يفقدنا بعض الفوائد المهمة. لكنها بداية ممتازة لفهم المبدأ.
الطريقة المتقدمة: استخدام خدمات متخصصة
هنا تكمن القوة الحقيقية. هناك العديد من الخدمات (SaaS) والحلول المفتوحة المصدر (Open Source) التي توفر بنية تحتية كاملة لإدارة أعلام الميزات. من أشهرها LaunchDarkly, Optimizely, Flagsmith، وهناك حلول مفتوحة المصدر رائعة مثل Unleash.
هذه الخدمات توفر لك:
- لوحة تحكم ويب: لتشغيل وإطفاء الأعلام بكبسة زر.
- تحديثات فورية: تتغير حالة العلم في تطبيقك خلال ثوانٍ بدون إعادة نشر.
- استهداف متقدم: يمكنك تفعيل ميزة لمستخدمين في دولة معينة، أو لمستخدمي أندرويد فقط، أو للمشتركين في الباقة المدفوعة، أو حتى لقائمة محددة من المستخدمين.
- تسجيل وتدقيق: تعرف من الذي غيّر العلم ومتى.
مثال كود (باستخدام مكتبة وهمية تحاكي الخدمات الحقيقية)
// 1. في بداية تشغيل التطبيق، نقوم بتهيئة العميل
const featureClient = new FeatureFlagClient({ sdkKey: 'YOUR_SDK_KEY' });
// 2. عند التعامل مع طلب مستخدم
async function handleRequest(request) {
const user = {
id: request.user.id,
country: request.user.country,
plan: request.user.subscriptionPlan
};
// 3. نفحص العلم مع تمرير معلومات المستخدم
const showNewFeature = await featureClient.isEnabled(
'awesome-new-feature', // اسم العلم
user, // معلومات المستخدم للاستهداف المتقدم
false // القيمة الافتراضية إذا حدث خطأ
);
if (showNewFeature) {
// ...
} else {
// ...
}
}
نصائح من خبرة أبو عمر: لا تقع في هذه الفخاخ!
أعلام الميزات أداة قوية، ولكن كأي أداة، إذا أسيء استخدامها قد تسبب مشاكل. إليك بعض النصائح من قلب التجربة:
1. نظّف أعلامك القديمة (Clean up your flags)
هذا هو الخطأ الأكثر شيوعاً. بعد أن يتم إطلاق الميزة بنسبة 100% وتثبت استقرارها، يجب عليك تخصيص وقت لإزالة العلم من الكود. احذف جملة الـ if/else والكود القديم. إذا لم تفعل ذلك، سيتحول كودك إلى غابة من الشروط المعقدة، وهذا ما يسمى “الدين التقني” (Technical Debt).
2. لا تضع منطق العمل داخل الأعلام
يجب أن تكون الأعلام غبية وبسيطة. وظيفتها فقط أن تقول “نعم” أو “لا”. لا تضع بداخل نظام الأعلام نفسه منطقاً معقداً. المنطق يجب أن يبقى في الكود البرمجي الخاص بك، والعلم هو الذي يقرر أي مسار من المنطق سيتم تنفيذه.
3. اجعل الأعلام جزءاً من ثقافة الفريق
يجب أن يفهم مديرو المنتجات، والمصممون، ومهندسو الجودة ما هي أعلام الميزات. يجب أن تصبح لغة مشتركة. مدير المنتج يجب أن يطلب “نريد هذه الميزة خلف علم”، وفريق الجودة يجب أن يعرف كيف يختبر الميزة بوجود العلم وبدونه.
4. ابدأ بسيطاً ثم تطور
لا تشعر أنه يجب عليك استخدام خدمة مدفوعة ومعقدة من اليوم الأول. ابدأ بملف إعدادات بسيط. عندما تبدأ بالشعور بألم قيود هذه الطريقة (مثلاً، “يا ليتني أستطيع تفعيل هذا لمستخدم واحد فقط!”)، عندها يكون الوقت قد حان للانتقال إلى حل أكثر تقدماً.
الخلاصة: من الجحيم إلى النعيم البرمجي 🧘
يا جماعة، من الآخر، تبني أعلام الميزات كان أحد أفضل القرارات التقنية التي اتخذناها. حولت عمليات النشر من حدث مرعب ومثير للتوتر إلى إجراء روتيني وممل. أعطتنا الثقة لنكون أسرع في الابتكار، وأعطتنا شبكة أمان لإصلاح المشاكل بسرعة البرق.
المبدأ الجوهري هو: افصل بين نشر الكود وإطلاق القيمة للمستخدم.
إذا كنت لا تزال تعاني من “كوابيس ما بعد النشر”، فأتمنى أن تكون هذه المقالة قد فتحت عينيك على طريقة جديدة. لا تخافوا من التجربة. ابدأوا اليوم بـ ‘علم’ واحد لميزة صغيرة، وشوفوا كيف رح يتغير عالمكم للأفضل. صدقوني، لن تندموا.
بالتوفيق في رحلتكم البرمجية! 🚀