عندما لا يكفي الصواب والخطأ البسيط: وضع أعلام الميزات في الكود الخاص بك
لقد بنيت ميزة جديدة. الكود يترجم، الاختبارات تمر، وأنت مستعد للنشر. لكنك لا تريد تفعيل المفتاح للجميع دفعة واحدة. ربما تريد المختبِرين الداخليين أولاً. ربما المستخدمين في آسيا فقط. ربما 10% فقط من الحركة.
هنا يأتي دور أعلام الميزات (Feature Flags). إنها تتيح لك فصل النشر عن الإصدار: يمكنك وضع كود جديد في الإنتاج دون جعله مرئيًا للجميع. ولكن كيف تضع هذه الأعلام في الكود الخاص بك بالضبط دون تحويله إلى فوضى من الشروط المتشابكة؟
أبسط علم: مفتاح منطقي (Boolean Switch)
في جوهره، علم الميزة هو مجرد فرع شرطي. إذا كان العلم قيد التشغيل، قم بتشغيل الكود الجديد. إذا كان متوقفًا، قم بتشغيل الكود القديم. الشكل الأساسي يبدو هكذا:
if fiturXEnabled:
show_new_feature()
else:
show_old_feature()
هنا، fiturXEnabled هو متغير منطقي. اضبطه على True، وسيرى المستخدمون الميزة الجديدة. اضبطه على False، وسيرون القديمة. بسيط.
لكن هناك مشكلة: يجب تحديد قيمة العلم قبل تشغيل الكود. إذا أردت تغييرها دون إعادة النشر، فأنت بحاجة لقراءة القيمة من مكان خارج الكود نفسه. يمكن أن يكون ذلك ملف إعدادات، متغير بيئة، أو خدمة عن بُعد. سنغطي التحكم عن بُعد في الأعلام لاحقًا، لكن الآن، دعنا نركز على متى يكون العلم المنطقي البسيط كافيًا.
يعمل العلم المنطقي بشكل جيد عندما تكون ميزتك صغيرة وتحتاج فقط إلى حالتين: تشغيل أو إيقاف. على سبيل المثال، تخيل زر "طباعة تقرير" كان مقتصرًا سابقًا على المسؤولين. الآن تريد فتحه لجميع المستخدمين. تضيف علمًا يسمى printReportForAllUsers. عندما يكون True، يظهر الزر للجميع. عندما يكون False، يراه المسؤولون فقط. انتهى.
عندما لا يكفي البسيط: الأعلام الشرطية (Conditional Flags)
أحيانًا تحتاج إلى مزيد من الدقة. ربما يجب أن تكون الميزة الجديدة مرئية فقط للمستخدمين بمعرفات محددة. ربما فقط المستخدمين في منطقة معينة. ربما فقط 10% من الحركة، يتم اختيارهم عشوائيًا. لا يمكن للمنطق البسيط التعامل مع هذا.
تحتاج إلى علم شرطي. العلم نفسه لا يزال منطقيًا، لكن المنطق الذي يحدد قيمته يعتمد على السياق. الطريقة الأبسط هي إضافة شروط خارج العلم:
if fiturXEnabled and user.id in trial_user_list:
show_new_feature()
else:
show_old_feature()
هذا يعمل، لكن trial_user_list يجب إدارتها بشكل منفصل. إذا تغيرت القائمة بشكل متكرر، فأنت بحاجة إلى طريقة لتحديثها دون إعادة النشر. هذا يضيف تعقيدًا.
الطريقة الأنظف هي استخدام موفر العلم (Flag Provider). موفر العلم هو دالة أو مكتبة تقبل السياق (مثل معرف المستخدم، المنطقة، نوع الجهاز) وتعيد قيمة العلم بناءً على قواعد محددة مسبقًا. يصبح الكود الخاص بك:
if flag_provider.is_enabled("featureX", user=current_user):
show_new_feature()
else:
show_old_feature()
في الخلفية، يتحقق موفر العلم من القواعد: هل هذا المستخدم في المجموعة التجريبية؟ هل منطقته متطابقة؟ هل تم استيفاء النسبة المئوية للحركة؟ لا تحتاج إلى إعادة كتابة هذا المنطق في كل مرة تستخدم فيها العلم.
الحفاظ على نظافة الكود الخاص بك
كلما أضفت المزيد من الأعلام، ظهرت المزيد من الفروع الشرطية في الكود الخاص بك. بدون انضباط، ينتهي بك الأمر بعبارات if متداخلة يصعب قراءتها وصيانتها.
بعض المبادئ تساعد:
علم واحد، مسؤولية واحدة. لا تحشر شروطًا متعددة في علم واحد. إذا كنت بحاجة للتحكم في الرؤية حسب المنطقة ودور المستخدم، استخدم علمين منفصلين. إنه أوضح وأسهل للإزالة لاحقًا.
ضع الأعلام في المستوى الصحيح. ضع العلم في أقرب نقطة ممكنة من نقطة دخول الميزة. بالنسبة لمكون واجهة المستخدم، قد تكون دالة العرض الخاصة به. بالنسبة لنقطة نهاية API، قد تكون المعالج. تجنب نشر نفس العلم عبر طبقات متعددة من الكود الخاص بك.
خطط لإزالة العلم. كل علم تضيفه هو كود مؤقت. عندما يتم طرح الميزة بالكامل، ستزيل مسار الكود القديم والعلم. اكتب أعلامك بحيث يسهل العثور عليها وحذفها. جمّع الأعلام ذات الصلة معًا. استخدم تسمية متسقة مثل featureX_enabled أو featureX_percentage.
قائمة تحقق عملية
قبل كتابة علم الميزة التالي، راجع هذه النقاط:
- هل يمكن التحكم في هذه الميزة باستخدام منطق بسيط، أم تحتاج إلى منطق شرطي؟
- من أين ستأتي قيمة العلم؟ مشفرة، ملف إعدادات، متغير بيئة، أو خدمة عن بُعد؟
- هل تم وضع العلم في المستوى الصحيح، بالقرب من مكان استخدام الميزة؟
- هل للعلم مسؤولية واحدة واضحة؟
- هل خططت لكيفية إزالة العلم ومسار الكود القديم لاحقًا؟
ما التالي
بمجرد وضع العلم في الكود، السؤال التالي هو كيفية تغيير قيمته دون إعادة النشر. تحتاج إلى طريقة للتحكم في الأعلام عن بُعد، سواء من خلال ملف إعدادات يتم إعادة تحميله، متغيرات بيئة يتم تحديثها، أو لوحة تحكم مخصصة. هنا تظهر القوة الحقيقية لأعلام الميزات: يمكنك تشغيل الميزات وإيقافها، طرحها تدريجيًا، والتفاعل مع المشكلات دون لمس خط أنابيب النشر.
لكن لا شيء من هذا يهم إذا كانت أعلامك فوضوية. ابدأ بأعلام نظيفة وموضوعة بشكل جيد في الكود الخاص بك. الباقي سيتبع.