متى يمكن للمستخدمين استخدام الميزة الجديدة فعليًا؟
لقد نشرت للتو ميزة جديدة إلى بيئة الإنتاج. الفريق مرتاح. تم إغلاق التذكرة. ولكن بعد ذلك تبدأ الأسئلة: "هل يمكننا الإعلان عنها الآن؟" "هل يجب أن ننتظر فريق التسويق؟" "ماذا لو ظهرت تلك الحالة الحدية التي فاتتنا تحت حركة المرور الحقيقية؟"
هذه اللحظة أكثر شيوعًا مما يعترف به معظم الفرق. الكود موجود على الخادم، لكن لا أحد متأكد مما إذا كان يجب على المستخدمين رؤيته بالفعل. وهذا الغموض يكشف عن فجوة لا يدركها العديد من الفرق حتى يحدث خطأ ما.
النشر ليس إطلاقًا
إليك تمييز يغير طريقة تفكيرك في شحن البرمجيات: نشر الكود وإطلاق الميزة شيئان مختلفان.
النشر هو فعل وضع كود جديد على الخادم. الإطلاق هو اللحظة التي يمكن للمستخدم فيها رؤية واستخدام تلك الميزة. في العديد من الفرق، يحدث هذان الحدثان في نفس الوقت افتراضيًا. الكود يصعد، الميزة تظهر. لكن ليس من الضروري أن يكونا مرتبطين.
تخيل أنك تدير تطبيقًا يستخدمه آلاف الأشخاص. لقد أضفت للتو ميزة بحث أسرع. تم نشر الكود على كل خادم. ولكن بعد التشغيل، تسببت الميزة في ارتفاع حمل الخادم. يبدأ المستخدمون في تجربة صفحات بطيئة. البعض لا يستطيع حتى فتح الصفحة الرئيسية. الآن لديك مشكلة خطيرة: تحتاج إلى التراجع عن التطبيق بأكمله، على الرغم من أن ميزة واحدة فقط معطلة. أو عليك كتابة إصلاح، والخضوع لعملية النشر بأكملها مرة أخرى، والأمل في أن تعمل هذه المرة. يتأثر المستخدمون طوال الوقت.
هذا الموقف يمكن تجنبه إذا تمكنت من فصل وقت وصول الكود إلى الخادم عن وقت ظهور الميزة للمستخدمين. يمكنك نشر كود يحتوي بالفعل على الميزة الجديدة، ولكن مع إبقاء تلك الميزة مغلقة. فقط بعد التأكد من أن كل شيء آمن، تقوم بتشغيلها.
يوضح مخطط التسلسل التالي كيف يُنشئ علم الميزة فجوة آمنة بين نشر الكود وإطلاقه للمستخدمين:
أعلام الميزات: مفتاح في الكود الخاص بك
الآلية لهذا الفصل تسمى علم الميزة (Feature Flag). علم الميزة هو مفتاح شرطي في الكود الخاص بك يحدد ما إذا كانت ميزة معينة يجب أن تعمل. يمكنك تغيير قيمة هذا المفتاح دون نشر كود جديد. قم بتحديث إعدادات، وتنشط الميزة أو تُعطل في التطبيق الجاري.
إليك مثال بسيط. بدلاً من استدعاء منطق البحث الجديد مباشرة، تقوم بتغليفه في فحص:
if feature_flags.is_enabled("fast_search"):
results = fast_search(query)
else:
results = old_search(query)
عندما يكون fast_search معطلاً، يقوم التطبيق بتشغيل مسار الكود القديم. عندما تقوم بتمكينه، يبدأ المنطق الجديد في العمل. لا حاجة للنشر من أجل التبديل.
يمنحك هذا التحكم في الوقت الذي يبدأ فيه المستخدمون باستخدام ميزة. يمكنك النشر متى شئت دون القلق من أن المستخدمين سيتأثرون فورًا بعمل غير مكتمل. يمكنك اختبار الميزة في الإنتاج مع مجموعة محدودة من المستخدمين أولاً. يمكنك تعطيل ميزة إشكالية في ثوانٍ دون التراجع عن التطبيق بأكمله.
ما تمكنه أعلام الميزات
بمجرد أن تصبح أعلام الميزات في مكانها، تصبح عدة أنماط عملية ممكنة.
الطرح التدريجي. بدلاً من إطلاق ميزة لجميع المستخدمين مرة واحدة، يمكنك تمكينها لنسبة 1% من المستخدمين، ثم 10%، ثم 50%. إذا حدث خطأ ما عند 10%، تلتقطه قبل أن يؤثر على الجميع. هذا مفيد بشكل خاص للميزات التي يصعب اختبارها في بيئة التدريج لأنها تعتمد على أنماط حركة المرور الحقيقية أو حجم البيانات.
الإصدارات التجريبية (Canary releases). يمكنك توجيه مجموعة صغيرة من المستخدمين إلى الميزة الجديدة بينما يبقى الجميع على السلوك القديم. راقب معدلات الخطأ، وزمن الاستجابة، وسلوك المستخدم. إذا لم تظهر المجموعة التجريبية أي مشاكل، قم بتوسيع الطرح. إذا ظهرت مشاكل، قم بإيقاف تشغيلها فورًا.
مفتاح الإيقاف الطارئ. عندما تسبب ميزة مشاكل غير متوقعة في الإنتاج، يمكنك تعطيلها فورًا. لا حاجة لعكس التغييرات، لا حاجة لإعادة البناء والنشر. فقط اقلب العلم إلى إيقاف. هذا يقلل الضغط على الفريق لأنك تعلم أنه يمكنك دائمًا سحب القابس بسرعة.
الاختبار في الإنتاج. يبدو هذا محفوفًا بالمخاطر، لكنه في الواقع أكثر أمانًا من البديل. باستخدام أعلام الميزات، يمكنك تمكين ميزة للمستخدمين الداخليين أو مختبري النسخة التجريبية أولاً. يستخدمون الميزة ببيانات حقيقية وسير عمل حقيقي. تلتقط المشاكل قبل أن تصل الميزة إلى قاعدة المستخدمين الأوسع.
الإصدارات المنسقة. أحيانًا تحتاج الميزة إلى التشغيل في وقت محدد لأسباب تجارية. ربما لدى فريق التسويق حملة مخطط لها. ربما تكون الميزة مرتبطة بموعد تنظيمي. باستخدام أعلام الميزات، يمكنك نشر الكود قبل أيام أو أسابيع وتمكينه في اللحظة المحددة التي يجب أن يكون متاحًا فيها.
تكلفة أعلام الميزات
أعلام الميزات ليست مجانية. إنها تضيف تعقيدًا إلى قاعدة الكود الخاصة بك. كل علم يقدم فرعًا شرطيًا يحتاج إلى اختبار. إذا تراكمت الأعلام بمرور الوقت، يصبح الكود أصعب في القراءة والصيانة. الأعلام القديمة التي تكون دائمًا مفعلة أو دائمًا معطلة تنشئ مسارات كود ميتة تربك المطورين المستقبليين.
هناك أيضًا التكلفة التشغيلية. تحتاج إلى طريقة لإدارة تكوينات الأعلام عبر البيئات. تحتاج إلى تحديد ما إذا كانت الأعلام تُقيّم على مستوى الخادم، أو مستوى المستخدم، أو مستوى آخر. تحتاج إلى ضمان أن تغييرات العلم تنتشر بسرعة وموثوقية.
الخطأ الأكثر شيوعًا الذي ترتكبه الفرق هو معاملة أعلام الميزات على أنها دائمة. يجب أن يكون للعلم دورة حياة واضحة: يتم تقديمه لغرض محدد، ويبقى نشطًا أثناء طرح الميزة، ويتم إزالته بمجرد أن تصبح الميزة منشورة بالكامل ومستقرة. الأعلام التي تبقى في الكود إلى الأبد تصبح ديونًا تقنية.
قائمة مراجعة عملية لاستخدام أعلام الميزات
إذا قررت اعتماد أعلام الميزات، إليك قائمة مراجعة قصيرة للحفاظ على الأمور تحت السيطرة:
- ابدأ بتنفيذ بسيط. ملف تكوين JSON أو متغير بيئة كافٍ للفرق الصغيرة. تجنب الإفراط في هندسة نظام العلم قبل فهم احتياجاتك.
- سمِّ الأعلام بوضوح. استخدم أسماء تصف الميزة، وليس تفاصيل التنفيذ.
fast_searchأفضل منsearch_v2_algorithm. - أزل الأعلام بعد أن تصبح الميزة مستقرة. ضع تذكيرًا أو أنشئ تذكرة لتنظيف كود العلم بمجرد اكتمال الطرح.
- اختبر حالتي العلم. تأكد من أن اختباراتك تغطي السلوك عندما يكون العلم قيد التشغيل وعندما يكون متوقفًا. العلم الذي يكسر مسار الكود القديم أسوأ من عدم وجود علم على الإطلاق.
- سجل تقييمات العلم. عند تصحيح مشاكل الإنتاج، تحتاج إلى معرفة أي الأعلام كانت نشطة لأي مستخدمين وفي أي وقت.
- حدد عدد الأعلام النشطة. كثرة الأعلام تجعل الكود صعب الفهم. إذا كان لديك عشرات الأعلام النشطة في نفس الوقت، فكر فيما إذا كنت تستخدم الأعلام لأشياء يجب أن تكون إعدادات دائمة.
الخلاصة
في المرة القادمة التي ينهي فيها فريقك ميزة، اطرح هذا السؤال: "هل تم نشر الكود، أم تم إطلاق الميزة؟" إذا كانت الإجابة هي نفسها افتراضيًا، فأنت تفوت فرصة للشحن بأمان أكبر وبتوتر أقل. تمنحك أعلام الميزات القدرة على فصل هذين الحدثين. إنها تسمح لك بالنشر وفقًا لجدولك الزمني والإطلاق عندما تكون مستعدًا. ابدأ بعلم واحد لميزتك الخطرة التالية. وانظر كيف يغير طريقة تفكير فريقك في الشحن.