Feature Flag — تکنیک توسعهای است که در آن کارکرد برنامه با استفاده از کلیدهای شرطی در زمان اجرا فعال یا غیرفعال میشود، بدون استقرار کد جدید. به جای رویکرد سنتی «کمیت کن — دپلوی کن»، feature flags امکان جداسازی لحظه دپلوی از لحظه فعالسازی ویژگی را فراهم میکنند. به استناد به LaunchDarkly (2024)، تیمهایی که از feature flags استفاده میکنند، زمان استقرار ویژگیهای جدید را 40% کاهش میدهند. فلاگهای ویژگی به عنوان عنصری اجباری CI/CD برای برنامههای موبایل و وب مدرن درآمدهاند.
نکات کلیدی
Feature Flag (فلاگ ویژگی، feature toggle) — مکانیسمی است که بدون تغییر کد، تغییر رفتار برنامه را ممکن میسازد. در سادهترین شکل، این یک ساختار شرطی است که قبل اجرای کارکرد جدید، مقدار فلاگ را بررسی میکند. فلاگ میتواند در فایل پیکربندی، پایگاه داده یا خدمت خارجی ذخیره شود و در زمان واقعی تغییر کند. این رویکرد به تیمها امکان میدهد کد ناتمام را در شاخه اصلی کمیت کنند بدون اینکه نگران باشند که به کاربران قبل از تکمیل توسعه میرسد.
هدف اصلی feature flags — جداسازی دپلوی و انتشار است. دپلوی فرآیند قراردادن کد در سرور یا فروشگاه برنامه است. انتشار لحظهای است که کارکرد برای کاربر دسترس میشود. بدون feature flags این رویدادها مصادف میشوند: کد به تولید میرود — کاربران آن را میبینند. با feature flags، کد میتواند هفتهها زودتر از انتشار در تولید مستقر شود، برای آزمایش داخلی فعال شود یا تدریجاً برای مخاطب انتشار یابد. این برای trunk-based development و continuous delivery حیاتی است.
پیادهسازی پایه 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()
}
}
همه feature flags یکسان نیستند. مارتین فولر در طبقهبندی خود چهار نوع فلاگ را جدا کرده که از نظر هدف استفاده، مدت زمان و نیازمندیهای مدیریتی متفاوت هستند. طبقهبندی درست فلاگها به انتخاب زیرساخت مناسب کمک میکند و از مشکلات تیپیکی جلوگیری میکند.
Release toggles — متداولترین نوع فلاگ است. آنها برای مخفی کردن کارکرد ناتمام در محیط تولید استفاده میشوند. توسعهدهنده کد را در شاخه اصلی کمیت میکند، در فلاگ پیچیده شده، و تدریجاً کارکرد را تکمیل میکند. پس از تکمیل و آزمایش، فلاگ برای تمام کاربران فعال میشود. چرخه عمر چنین فلاگی چند روز تا دو هفته است. پس از انتشار کامل، فلاگ از کد حذف میشود. Release toggles اساس trunk-based development هستند.
Experiment toggles همراه با آزمایشهای A/B کار میکنند. آنها فقط کارکرد را فعال/غیرفعال نمیکنند، بلکه کاربر را به یکی از گروههای آزمایشی هدایت میکنند. چنین فلاگهایی اغلب قوانین هدفگیری پیچیده (بر اساس منطقه، نسخه OS، اشتراک) و یکپارچگی با سیستمهای تحلیل را پشتیبانی میکنند. Ops toggles برای کنترل عملیاتی استفاده میشوند — برای مثال، غیرفعال کردن یک ویژگی سنگین در زمان بار بالا یا غیرفعال موقت یک ماژول مشکلدار بدون دپلوی فوری. Ops toggles باید حداکثر سریع و قابل اطمینان باشند، زیرا پایداری خدمات به آنها بستگی دارد.
| نوع | مدت | پویایی | هدف |
|---|---|---|---|
| Release | روز-هفته | ثابت | مخفیسازی کد ناتمام |
| Experiment | روز-ماه | پویا | آزمایشهای A/B و انتشار |
| Ops | ساعت-روز | پویا | کنترل عملیاتی |
| Permission | ماه+ | استاتیک | تمایز دسترسی |
مدیریت feature flags یک رشته جداگانه است که شامل ذخیره، پیکربندی، نظارت و حسابرسی فلاگها است. بدون سیستم مدیریتی، فلاگها به بدهی فنی غیرقابل کنترل تبدیل میشوند و توسعه را کند میکنند. جنبههای کلیدی مدیریت را در مثال یک سیستم تولید بررسی میکنیم.
هر feature flag از چهار مرحله عبور میکند: ایجاد، استفاده، پایدارسازی و حذف. در مرحله ایجاد، کلید فلاگ، نوع و مقدار پیشفرض تعیین میشود. در طول استفاده، تیم نظارت میکند که کی فلاگ را برای چه مخاطبی و به چه منظوری فعال کرده است. پس از پایدارسازی (کارکرد کاملاً آماده و آزموده شده)، فلاگ باید از کد حذف شود. فرآیند حذف از طریق بررسی کد خودکار میشود: CI بررسی میکند که آیا همه فلاگهایی که برای 100% کاربران فعال هستند، وظیفه حذف دارند.
Feature flags باید به صورت متمرکز ذخیره شوند، نه پراکنده در فایلهای پیکربندی هر خدمات. ایدهآل — یک خدمت جداگانه با راهانداز (LaunchDarkly، Unleash). حداقل گزینه قابل قبول — پیکربندی JSON در مخزن با بررسی کد در تغییرات. پایگاه داده برای ذخیره فلاگها کمتر ترجیح دارد، زیرا به راهانداز جداگانه برای مدیریت نیاز دارد. هر فلاگ باید صاحب (تیم یا توسعهدهنده مشخص)، توضیح و مدت زمان اعتبار داشته باشد. حسابرسی منظم فلاگهای منقضی یک رویه اجباری است که از طریق وظیفه CI خودکار میشود و فلاگهایی را که بیش از N روز تغییر نکردهاند بررسی میکند.
بازار ابزارهای مدیریت feature flags هم پلتفرمهای تجاری با چرخه مدیریت کامل و هم راهحلهای منبعباز برای استقرار مستقل را شامل میشود. انتخاب ابزار به میزان تیم، نیازمندیهای تاخیر و مطابقت بستگی دارد.
LaunchDarkly — رهبر بازار با SDK برای تمام زبانها و پلتفرمهای محبوب (iOS، Android، Web، Backend). از چند محیط، هدفگیری مبتنی بر قاعده، آزمایشهای A/B و حذف خودکار فلاگها پشتیبانی میکند. Split — الترناتیو با تمرکز بر ویژگیهای سازمانی: دسترسی مبتنی بر نقش، سبت حسابرسی و مطابقت (SOC2، HIPAA). ConfigCat — راهحل سبکتر و قابل دسترستر، مناسب برای تیمهای کوچک. همه پلتفرمها SDK با ذخیرهسازی مقادیر و تاثیر حداقل بر تاخیر برنامه ارائه میدهند.
Unleash — محبوبترین راهحل منبعباز با راهانداز، API و SDK برای تمام پلتفرمهای اصلی. از راهبردهای فعالسازی، زمینههای سفارشی و یکپارچگی با Prometheus برای نظارت پشتیبانی میکند. Flagsmith — الترناتیو با آزمایش A/B داخلی و مدیریت محیط. راهحلهای منبعباز نیازمند میزانسازی و پشتیبانی از زیرساخت هستند، اما کنترل کامل بر دادهها را فراهم میکنند و محدودیت مجوز ندارند. برای برنامههای موبایل، هر دو راهحل SDK اصلی با ذخیرهسازی آفلاین مقادیر فلاگ را ارائه میدهند.
Feature flags ابزاری قدرتمند هستند، اما بدون انضباط بدهی فنی ایجاد میکنند و کد را پیچیده میکنند. مارتین فولر و مهندسان LaunchDarkly مجموعهای از رویهها را تدوین کردهاند که به استخراج حداکثر فایده از feature flags بدون پیامدهای منفی کمک میکند. توصیههای کلیدی برای سیستمهای تولید را بررسی میکنیم.
هر feature flag که پس از اتمام انتشار حذف نشده، به بدهی فنی تبدیل میشود. تحقیق LaunchDarkly (2024) نشان داد که به طور میانگین 30–40% فلاگها پس از بی نیازی در کد باقی میمانند. راهحل: اصل «یک فلاگ — یک وظیفه» را پیاده کنید. هنگام ایجاد فلاگ، یک وظیفه برای حذف آن در پیگیر وظیفه ایجاد شود. CI بررسی میکند که هیچ فلاگی برای 100% کاربران بیش از 30 روز فعال نمانده باشد. بررسی کد نباید فقط افزودن، بلکه حذف فلاگها را نیز بررسی کند.
Feature flags برای آزمایش پیچیدگی ترکیبی ایجاد میکنند: هر فلاگ تعداد وضعیتهای ممکن برنامه را دو برابر میکند. برای مدیریت این پیچیدگی، آزمایشهای ماتریسی که تمام ترکیبات فلاگ را بررسی میکند و آزمایشهای یکپارچگی تغییر فلاگ استفاده میشوند. در خط لوله CI یک مرحله افزوده میشود که آزمایشها را با ترکیبات مختلف مقادیر فلاگ اجرا میکند. برای فلاگهای حیاتی (ops toggles)، آزمایشهای بار اجباری هستند که تغییر فلاگ باعث افزایش تاخیر یا خطا نمیشود.
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 معمولاً به یک سیستم پیشرفتهتر با مدیریت متمرکز، راهانداز و SDK اشاره دارد، در حالی که feature toggle یک کلید دودویی ساده در کد است. مارتین فولر از feature toggle به عنوان یک اصطلاح عمومی استفاده میکند، اما در صنعت، feature flag بیشتر با پلتفرمهای تجاری (LaunchDarkly، Split) مرتبط است.
تاثیر بر عملکرد در پیادهسازی صحیح حداقل است. رویههای بهتر: ذخیرهسازی مقادیر فلاگ در حافظه با TTL 30–60 ثانیه، اجتناب از تماسهای HTTP همزمان در بررسی فلاگ، استفاده از SDK با کش محلی و همگامسازی پسزمینه. به استناد به LaunchDarkly، p99 latency SDK آنها کمتر از 5 میلیثانیه است که برای اکثر برنامهها ناچیز است.
Feature flags برای تغییر منطق کسب و کار در عملیات حیاتی مالی توصیه نمیشود، جایی که دانستن کدام کد در حال اجراست حیاتی است. همچنین باید از فلاگ برای ویژگیهای امنیتی (مجوزدهی، رمزگزاری) خودداری کرد — غیرفعال کردن چنین فلاگی یک آسیبپذیری ایجاد میکند. برای تغییرات زیرساختی (تغییر پایگاه داده، مهاجرت به معماری جدید) feature flags مفید هستند اما نیازمند آزمایش بیشتر هستند.
رویکرد اصلی آزمایش ماتریسی است: اجرای آزمایشها با تمام ترکیبات فلاگ. برای CI/CD این میتواند گران باشد (2^n ترکیب)، بنابراین در عمل تمام فلاگها به صورت جداگانه در هر دو وضعیت (فعال/غیرفعال) آزمایش میشوند، و برای ترکیبات فقط حیاتی. آزمایشهای واحد باید مقدار فلاگ را mock کنند. آزمایشهای یکپارچگی سناریوهای مشخص را با مقادیر مشخص فلاگ بررسی میکنند. آزمایشهای E2E محتملترین ترکیبات را پوشش میدهند.
فرآیند حذف: 1) اطمینان حاصل کنید که فلاگ برای 100% کاربران فعال است و در حالت آزمایش استفاده نمیشود; 2) تمام بررسیهای شرطی فلاگ را از کد حذف کنید، فقط شاخه «جدید» را نگه دارید; 3) تعریف فلاگ را از سیستم مدیریت حذف کنید; 4) آزمایشها را با حذف mock های فلاگ حذفشده بهروز کنید. توصیه میشود این فرآیند را از طریق CI خودکار کنید: فلاگهایی که بیش از N روز تغییر نکردهاند به عنوان منقضی علامتگذاری میشوند و نیازمند تایید حذف هستند.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید