Feature Flag هي تقنية تطوير يتم من خلالها تمكين أو تعطيل وظائف التطبيق عبر مفاتيح شرطية في وقت التشغيل، دون نشر كود جديد. بدلاً من النهج التقليدي «commit — deploy»، تسمح أعلام الميزات بفصل لحظة النشر عن لحظة تفعيل الوظيفة. وفقًا لـ LaunchDarkly (2024)، فإن الفرق التي تستخدم أعلام الميزات تقلل وقت طرح الميزات الجديدة بنسبة 40%. أعلام الميزات أصبحت عنصرًا أساسيًا في CI/CD للتطبيقات الحديثة للهواتف المحمولة والويب.
النقاط الرئيسية
Feature Flag (مفتاح الميزة) هو آلية تسمح بتغيير سلوك التطبيق دون تعديل الكود. في أبسط أشكاله، هو بناء شرطي يتحقق من قيمة العلم قبل تنفيذ وظيفة جديدة. يمكن تخزين العلم في ملف تهيئة أو قاعدة بيانات أو خدمة خارجية وتغييره في الوقت الفعلي. يمنح هذا النهج الفرق القدرة على إرسال كود غير مكتمل إلى الفرع الرئيسي دون الخوف من وصوله إلى المستخدمين قبل اكتمال التطوير.
الغرض الرئيسي من أعلام الميزات هو فصل النشر عن الإطلاق. النشر هو عملية وضع الكود على خادم أو في متجر التطبيقات. الإطلاق هو اللحظة التي تصبح فيها الوظيفة متاحة للمستخدم. بدون أعلام الميزات، تتزامن هذه الأحداث: يخرج الكود إلى الإنتاج — يراه المستخدمون. مع أعلام الميزات، يمكن نشر الكود في الإنتاج قبل أسابيع من الإطلاق، وتفعيله للاختبار الداخلي أو طرحه تدريجيًا للجمهور. هذا أمر بالغ الأهمية للتطوير القائم على الفرع الرئيسي والتسليم المستمر.
لنفكر في تنفيذ أساسي لعلم الميزة في تطبيق جوال بلغة Kotlin. يتم تخزين العلم في Firebase Remote Config ويتم تحميله عند بدء التطبيق. اعتمادًا على قيمة العلم، يتم عرض شاشة الملف الشخصي القديمة أو الجديدة. يسمح هذا التنفيذ بإطلاق نسخة جديدة من الملف الشخصي دون نشر تحديث في App Store — فقط قم بتغيير القيمة في وحدة تحكم Firebase.
class ProfileFeature {
private val flags = FeatureFlagProvider()
private val profileFlag = FlagKey("new_profile_enabled")
fun getProfileScreen(): Screen {
return if (flags.isEnabled(profileFlag)) {
NewProfileScreen()
} else {
LegacyProfileScreen()
}
}
}
class FeatureFlagProvider {
fun isEnabled(key: FlagKey): Boolean {
val raw = Firebase.remoteConfig.getString(key.name)
return raw.toBoolean()
}
}
ليست كل أعلام الميزات متشابهة. يصنف مارتن فاولر أربعة أنواع من الأعلام، تختلف في غرض الاستخدام ومدة الحياة ومتطلبات الإدارة. يساعد التصنيف الصحيح للأعلام في اختيار البنية التحتية المناسبة وتجنب المشكلات الشائعة.
أعلام الإصدار هي النوع الأكثر شيوعًا من الأعلام. تُستخدم لإخفاء الوظائف غير المكتملة في الإنتاج. يرسل المطور كودًا إلى الفرع الرئيسي مغلفًا بعلم ويكمل الوظيفة تدريجيًا. بعد الانتهاء والاختبار، يتم تفعيل العلم لجميع المستخدمين. يتراوح دورة حياة هذا العلم من بضعة أيام إلى أسبوعين. بعد الطرح الكامل، تتم إزالة العلم من الكود. أعلام الإصدار هي أساس التطوير القائم على الفرع الرئيسي.
أعلام التجربة تعمل بالتزامن مع اختبارات A/B. لا تقوم فقط بتشغيل أو إيقاف الوظائف، بل توجه المستخدم إلى إحدى المجموعات التجريبية. غالبًا ما تدعم هذه الأعلام قواعد استهداف معقدة (حسب المنطقة، إصدار نظام التشغيل، الاشتراك) والتكامل مع أنظمة التحليلات. أعلام التشغيل تُستخدم للتحكم التشغيلي — على سبيل المثال، تعطيل وظيفة ثقيلة تحت الحمل العالي أو إيقاف تشغيل وحدة مشكلة مؤقتًا دون نشر فوري. يجب أن تكون أعلام التشغيل سريعة وموثوقة قدر الإمكان، لأن استقرار الخدمة يعتمد عليها.
| النوع | المدة | الديناميكية | الغرض |
|---|---|---|---|
| Release | أيام-أسابيع | ثابت | إخفاء الكود غير المكتمل |
| Experiment | أيام-أشهر | ديناميكي | اختبارات A/B والطرح |
| Ops | ساعات-أيام | ديناميكي | التحكم التشغيلي |
| Permission | أشهر+ | ثابت | التحكم في الوصول |
إدارة أعلام الميزات هي تخصص منفصل يشمل التخزين والتكوين والمراقبة والتدقيق للأعلام. بدون نظام إدارة، تتحول الأعلام إلى دين تقني لا يمكن السيطرة عليه ويبطئ التطوير. دعنا ننظر في الجوانب الرئيسية للإدارة باستخدام نظام إنتاجي كمثال.
يمر كل علم ميزة بأربع مراحل: الإنشاء والاستخدام والتثبيت والإزالة. في مرحلة الإنشاء، يتم تحديد مفتاح العلم ونوعه وقيمته الافتراضية. أثناء الاستخدام، يراقب الفريق من قام بتفعيل العلم ولأي جمهور ولأي غرض. بعد التثبيت (اكتمال الوظيفة واختبارها بالكامل)، يجب إزالة العلم من الكود. تتم أتمتة عملية الإزالة من خلال مراجعة الكود: يتحقق CI من أن جميع الأعلام المفعلة بنسبة 100% لديها مهمة إزالة.
يجب تخزين أعلام الميزات بشكل مركزي، وليس مشتتة عبر ملفات التهيئة لكل خدمة. من الناحية المثالية — خدمة مخصصة بواجهة مستخدم (LaunchDarkly, Unleash). الخيار المقبول بالحد الأدنى هو ملف JSON في المستودع مع مراجعة الكود للتغييرات. قاعدة البيانات لتخزين الأعلام أقل تفضيلاً لأنها تتطلب واجهة إدارة منفصلة. يجب أن يكون لكل علم مالك (فريق أو مطور محدد) ووصف وفترة صلاحية (TTL). تدقيق الأعلام القديمة بانتظام هو ممارسة إلزامية، تتم آليًا عبر مهمة CI تتحقق من الأعلام التي لم تتغير لأكثر من N يومًا.
يشمل سوق أدوات إدارة أعلام الميزات كلاً من المنصات التجارية بدورة إدارة كاملة وحلول مفتوحة المصدر للنشر الذاتي. يعتمد اختيار الأداة على حجم الفريق ومتطلبات زمن الاستجابة والامتثال.
LaunchDarkly هي الرائدة في السوق مع SDKs لجميع اللغات والمنصات الشائعة (iOS و Android و Web و Backend). تدعم بيئات متعددة واستهدافًا قائمًا على القواعد وتجارب A/B وإزالة تلقائية للأعلام. Split هو بديل يركز على ميزات المؤسسات: وصول قائم على الأدوار وسجلات التدقيق والامتثال (SOC2, HIPAA). ConfigCat هو حل أخف وأكثر تكلفة مناسب للفرق الصغيرة. توفر جميع المنصات SDKs مع تخزين مؤقت للقيم وتأثير ضئيل على زمن استجابة التطبيق.
Unleash هو الحل الأكثر شيوعًا مفتوح المصدر مع واجهة مستخدم و API و SDKs لجميع المنصات الرئيسية. يدعم استراتيجيات التنشيط والسياقات المخصصة والتكامل مع Prometheus للمراقبة. Flagsmith هو بديل مع اختبارات A/B مدمجة وإدارة البيئات. تتطلب الحلول مفتوحة المصدر نشر البنية التحتية وصيانتها ولكنها تمنح تحكمًا كاملاً في البيانات وليس لها قيود ترخيص. للتطبيقات المحمولة، يوفر كلا الحلين SDKs أصلية مع تخزين مؤقت لقيم الأعلام دون اتصال.
أعلام الميزات هي أداة قوية، لكن بدون انضباط فإنها تخلق دينًا تقنيًا وتعقد الكود. صاغ مارتن فاولر ومهندسو LaunchDarkly مجموعة من الممارسات التي تساعد في تحقيق أقصى استفادة من أعلام الميزات دون عواقب سلبية. دعنا نستعرض التوصيات الرئيسية لأنظمة الإنتاج.
كل علم ميزة لم تتم إزالته بعد اكتمال الطرح يصبح دينًا تقنيًا. أظهرت دراسة LaunchDarkly (2024) أن ما متوسطه 30-40% من الأعلام تبقى في الكود بعد أن لم تعد هناك حاجة إليها. الحل: تنفيذ قاعدة «علم واحد — مهمة واحدة». عند إنشاء علم، يتم إنشاء مهمة إزالة بموعد نهائي في متتبع المهام. يتحقق CI من عدم وجود أعلام مفعلة بنسبة 100% لأكثر من 30 يومًا. يجب أن تتحقق مراجعة الكود ليس فقط من إضافة الأعلام بل أيضًا من إزالتها.
تخلق أعلام الميزات تعقيدًا توافقيًا للاختبار: كل علم يضاعف عدد الحالات المحتملة للتطبيق. لإدارة هذا التعقيد، تُستخدم اختبارات المصفوفة التي تتحقق من جميع تركيبات الأعلام واختبارات تكامل تبديل الأعلام. تتم إضافة خطوة إلى خط أنابيب CI تشغل اختبارات بتركيبات مختلفة لقيم الأعلام. للأعلام الحرجة (أعلام التشغيل)، اختبارات الحمل إلزامية للتحقق من أن تبديل العلم لا يسبب زيادات في زمن الاستجابة أو أخطاء.
class FeatureFlagService:
def __init__(self, storage):
self.storage = storage
def is_enabled(self, flag_key, user_context):
flag = self.storage.get(flag_key)
if not flag:
return False
for rule in flag["rules"]:
if self._match_rule(rule, user_context):
return rule["value"]
return flag["default"]
def _match_rule(self, rule, context):
return (
rule["percentage"] > self._hash(context.user_id)
)
الأسئلة الشائعة
غالبًا ما يُستخدم المصطلحان كمرادفين، لكن هناك فارق: feature flag يشير عادةً إلى نظام أكثر نضجًا مع إدارة مركزية وواجهة مستخدم و SDKs، بينما feature toggle هو مفتاح ثنائي بسيط في الكود. يستخدم مارتن فاولر feature toggle كمصطلح عام، لكن في الصناعة يرتبط feature flag غالبًا بالمنصات التجارية (LaunchDarkly, Split).
التأثير على الأداء ضئيل مع التنفيذ الصحيح. أفضل الممارسات: تخزين قيم الأعلام مؤقتًا في الذاكرة مع TTL من 30 إلى 60 ثانية، وتجنب استدعاءات HTTP المتزامنة عند التحقق من العلم، واستخدام SDKs مع تخزين مؤقت محلي ومزامنة خلفية. وفقًا لـ LaunchDarkly، فإن زمن الاستجابة p99 لـ SDK الخاص بهم أقل من 5 مللي ثانية، وهو غير مهم لمعظم التطبيقات.
لا يُنصح باستخدام أعلام الميزات لتغيير منطق الأعمال في العمليات المالية الحرجة حيث من المهم معرفة الكود الذي يتم تشغيله بالضبط. تجنب أيضًا الأعلام لوظائف الأمان (التفويض والتشفير) — تعطيل مثل هذا العلم يخلق ثغرة أمنية. للتغييرات في البنية التحتية (ترحيل قاعدة البيانات، الترحيل إلى بنية جديدة)، أعلام الميزات مفيدة ولكنها تتطلب اختبارًا دقيقًا بشكل خاص.
النهج الرئيسي هو اختبار المصفوفة: تشغيل الاختبارات مع جميع تركيبات الأعلام. بالنسبة لـ CI/CD، قد يكون هذا مكلفًا للغاية (2^n تركيبة)، لذلك عمليًا يتم اختبار جميع الأعلام بشكل فردي في كلتا الحالتين (تشغيل/إيقاف)، ويتم اختبار التركيبات الحرجة فقط. يجب أن تحاكي اختبارات الوحدة قيمة العلم. تتحقق اختبارات التكامل من سيناريوهات محددة بقيم أعلام معروفة. تغطي اختبارات E2E التركيبات الأكثر احتمالية.
عملية الإزالة: 1) تأكد من أن العلم مفعل بنسبة 100% لجميع المستخدمين ولا يُستخدم في وضع التجربة؛ 2) أزل جميع التحققّات الشرطية للعلم من الكود، مع الاحتفاظ فقط بالفرع «الجديد»؛ 3) أزل تعريف العلم من نظام الإدارة؛ 4) حدّث الاختبارات بإزالة المحاكاة للعلم المُزال. يُوصى بأتمتة هذه العملية عبر CI: الأعلام التي لم تتغير لأكثر من N يومًا تُعلّم كقديمة وتتطلب تأكيد الإزالة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا