Qué son los feature flags y por qué los necesita
\nImagine: ha escrito una nueva función genial, por ejemplo, una búsqueda inteligente con autocompletado. Todo está probado, el código ha pasado la revisión. Pero no está 100% seguro de que los usuarios la aceptarán. O teme que bajo carga falle. ¿Qué hacer?
\nAntes la respuesta era simple: "Despliega en producción y reza". Hoy somos más inteligentes. Usamos feature flags (banderas de funciones, interruptores de funciones), un mecanismo que permite activar y desactivar funcionalidades sobre la marcha, sin recompilación ni redeploy.
\nEn este artículo de PythonLib analizaremos cómo implementar feature flags en proyectos C#, desde la implementación más simple hasta escenarios avanzados con pruebas A/B y lanzamientos canarios.
\n\nPor qué los feature flags son imprescindibles para el desarrollador C#
\nFeature flags C# resuelven tres tareas clave:
\n- \n
- Despliegue seguro: suba código a producción incluso si la función aún no está lista. Simplemente desactive la bandera. \n
- Desactivación instantánea: ¿algo salió mal? Un clic en el panel de administración y la función problemática desaparece. \n
- Gestión flexible de funciones: active funciones para usuarios específicos, regiones o por tiempo. \n
Y lo mejor: para la gestión de funciones en .NET no necesita reinventar la rueda, existe la biblioteca lista Microsoft.FeatureManagement.
La forma más sencilla: archivo de configuración
\nEmpecemos con el enfoque básico: a través de appsettings.json. Es ideal para feature toggles .NET simples.
Paso 1. Agregamos configuraciones
\n{\n "FeatureManagement": {\n "NewSearchEngine": true,\n "DarkMode": false,\n "BetaDashboard": true\n }\n}\n\nPaso 2. Registramos el servicio
\nEn Program.cs agregamos:
builder.Services.AddFeatureManagement();\n\nPaso 3. Usamos en el código
\npublic class SearchController\n{\n private readonly IFeatureManager _featureManager;\n\n public SearchController(IFeatureManager featureManager)\n {\n _featureManager = featureManager;\n }\n\n public async Task<IActionResult> Search(string query)\n {\n if (await _featureManager.IsEnabledAsync("NewSearchEngine"))\n {\n return View("NewSearch", await _newEngine.SearchAsync(query));\n }\n return View("LegacySearch", await _oldEngine.SearchAsync(query));\n }\n}\n¡Listo! Ahora, para activar la nueva función, basta con cambiar true por false en la configuración y reiniciar la aplicación. Pero queremos hacerlo sin reinicio, ¿verdad?
Feature flags dinámicos: cambio sin reinicio
\nPara conditional features C# sin recarga, usamos proveedores de configuración que cargan los cambios. La mejor opción es una base de datos o Redis.
\n\nCreando un proveedor desde base de datos
\npublic class DatabaseFeatureDefinitionProvider : IFeatureDefinitionProvider\n{\n private readonly AppDbContext _db;\n\n public DatabaseFeatureDefinitionProvider(AppDbContext db)\n {\n _db = db;\n }\n\n public async Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)\n {\n var feature = await _db.FeatureFlags\n .FirstOrDefaultAsync(f => f.Name == featureName);\n \n return feature != null \n ? new FeatureDefinition { Name = feature.Name, EnabledFor = feature.EnabledFor }\n : null;\n }\n\n public IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()\n {\n return _db.FeatureFlags\n .Select(f => new FeatureDefinition { Name = f.Name, EnabledFor = f.EnabledFor })\n .AsAsyncEnumerable();\n }\n}\n\nRegistramos:
\nbuilder.Services.AddFeatureManagement