Compartir a través de


ALM Rangers

Desarrollo de software con conmutadores de función

Bill Heys

Descargar el código de muestra

Los conmutadores de característica como concepto de desarrollo de software permiten realizar el desarrollo de características concurrente en paralelo como alternativa a la bifurcación para el desarrollo en paralelo (también denominado bifurcaciones de características). Los conmutadores de característica se denominan a veces indicadores de característica, interruptores de característica, impulsores de característica o características condicionales. Los conmutadores de característica permiten integrar características continuamente mientras están bajo desarrollo. Puede utilizar los conmutadores de característica para ocultar, deshabilitar o habilitar características individuales durante el tiempo de ejecución.

Como con todas las técnicas de desarrollo de software, los conmutadores de característica se utilizan junto con el control de la versión (como Microsoft Team Foundation Server). La utilización de conmutadores de característica por sí sola no implica la eliminación de todas las bifurcaciones de un plan de control de la versión completa. Lo que distingue a los conmutadores de característica es que todos los cambios se comprueban en la bifurcación principal (línea principal) en lugar de hacerlo en una bifurcación de desarrollo.

Una característica se deshabilita u oculta para todos los usuarios hasta que empieza el desarrollo de la característica. Durante el desarrollo, puede habilitar la característica para el desarrollo y la prueba de la unidad y deshabilitarla para todos los demás usuarios. Los comprobadores de control de calidad (QA) también pueden habilitar las características que desean probar. Hasta que la característica se haya completado y comprobado totalmente según la definición de terminado (Definition of Done (DoD)) y pase las pruebas de calidad, se ocultará o deshabilitará en la versión del software. Puede cambiar dinámicamente el valor de un conmutador de función sin crear e implementar una nueva compilación.

Empezaré por una comparación de las bifurcaciones de característica y los conmutadores de característica, y sugeriré técnicas alternativas para implementar conmutadores de característica en el código. Utilizando una aplicación de calculadora de Windows de ejemplo, ilustraré cómo ocultar o mostrar características en tiempo de ejecución con conmutadores de característica.

Integración continua

Con los conmutadores de característica, puede realizar una integración continua, todo el trabajo de desarrollo se comprueba en la bifurcación principal y se integra continuamente con el resto de código de esa bifurcación. En cada registro, el código de la bifurcación principal se compila y se prueba en un servidor de compilación utilizando pruebas de comprobación de la compilación (BVT) automatizadas.

Como se indica en el manual de modelos y prácticas de Microsoft sobre la entrega continua (“Building a Release Pipeline with Team Foundation Server 2012” [2013]), la entrega continuada significa que a través de técnicas como la creación de versiones, la integración continua, la automatización y la administración del entorno, podrá reducir el tiempo entre la primera idea y su plasmación como software en la producción (bit.ly/1kFV0Kx).

Puede utilizar pruebas automatizadas de la unidad para probar el código antes de comprobarlo en la bifurcación principal. Si un registro interrumpe una compilación en el servidor de compilación, tendrá que arreglar el código antes de permitir el registro. Si una característica de la compilación no pasa una prueba de control de calidad, puede ocultarla de la implementación o versión hasta que lo haga.

Los conmutadores de característica ofrecen el aislamiento en tiempo de ejecución de una característica que se está desarrollando hasta que se ha completado, probado y está lista para la versión. Cuando se utilizan conmutadores de característica con integración continua, se trabaja directamente en la bifurcación principal. El código se comprueba en la bifurcación principal, mientras se conserva esta bifurcación estable para compilaciones e implementaciones (vea la Figura 1).

Feature Toggles Support Continuous Integration of Parallel Development
Figura 1 Los conmutadores de característica admiten la integración continua de desarrollo en paralelo

Conmutadores de característica en uso

La Figura 2 muestra un ejemplo de conmutadores de característica en forma de calculadora de Windows. También ilustra los retos del desarrollo de características concurrente en paralelo.

Sample Windows Calculator Showing Three New Features
Figura 2 Calculadora de Windows de ejemplo que muestra tres nuevas características

En este ejemplo se compara la administración del desarrollo en paralelo cuando se utilizan bifurcaciones de característica y cuando se utilizan conmutadores de característica. Tres características nuevas (Teclado, Funciones avanzadas y Funciones de memoria) se desarrollan en paralelo mientras se implementa la calculadora básica.

Modelos de conmutador de característica

Hay muchos modelos de uso en los que se pueden utilizar conmutadores de característica para permitir la integración continua de todo el código, incluyendo el código pendiente o incompleto. Los conmutadores de característica pueden aumentar la velocidad de desarrollo de un equipo reduciendo o eliminando la necesidad de bifurcaciones de desarrollo en paralelo y la sucesión de tareas de bifurcación y combinación, que necesitan mucho tiempo y son propensas a errores.

Esta es una lista de escenarios típicos en los que puede utilizar los conmutadores de característica:

  • Ocultación o deshabilitación de nuevas características en la IU
  • Ocultación o deshabilitación de nuevos componentes en la aplicación
  • Creación de versiones de una interfaz
  • Extensión de una interfaz
  • Soporte de varias versiones de un componente
  • Adición de una nueva característica a una aplicación existente
  • Mejora de una característica existente en una aplicación existente

Bifurcación para el aislamiento de características

Con una estrategia de bifurcación de características, el equipo puede aislar el desarrollo concurrente o paralelo de características (o grupos de características) específicas en bifurcaciones de característica independientes. Las bifurcaciones de característica ofrecen gran flexibilidad cuando se mueve una versión a producción. No es necesario esperar hasta que todas las características estén preparadas para hacer una implementación completa.

Puede combinar fácilmente características individuales o grupos de características en la bifurcación principal cuando estén completas según la DoD. Puede crear nuevas bifurcaciones de característica según necesite y suprimirlas cuando haya completado la función. Las características no se combinan en la bifurcación principal hasta que alcanzan la DoD. Siguiendo con el ejemplo, la Figura 3 muestra tres características nuevas que proporcionan aislamiento durante el desarrollo en paralelo.

Branching for Feature Isolation
Figura 3 Bifurcación para el aislamiento de características

Para obtener ayuda acerca de varios escenarios de bifurcación de características, puede consultar el e-book de ALM Rangers sobre las estrategias de bifurcación en aka.ms/vsarsolutions.

Conmutadores de característica en comparación a bifurcaciones de característica

La utilización de conmutadores de característica le permite a usted y a su equipo realizar prácticas de integración continua, implementación continua y lanzamientos continuos. Estas prácticas permiten la integración más frecuente de código de característica ya que se desarrollan en paralelo en comparación con las bifurcaciones de característica. Al mismo tiempo, los conmutadores de característica también admiten el aislamiento en tiempo de ejecución de características bajo desarrollo y no preparadas para su lanzamiento.

Con los conmutadores de característica, todos los cambios pendientes se comprueban en la bifurcación principal. Cada registro queda pendiente hasta que un proceso de compilación automatizado compila todo el código de la bifurcación principal en un servidor de compilación y ejecuta correctamente las BVT automatizadas. Este es el proceso conocido como integración continua.

En tiempo de ejecución, los conmutadores de característica ocultan o ignoran las características que se encuentran en la compilación, pero que no están preparadas para la versión. Según cómo tenga previsto implementar una característica, el intento de utilizar conmutadores de característica puede ser complejo a veces. Por otro lado, la ocultación de características de la IU puede ser un método más directo.

Cuando se utilizan bifurcaciones de característica, todo el desarrollo se comprueba en la bifurcación de característica asociada y se aísla del código de la bifurcación principal u otras bifurcaciones de característica. No se puede combinar una característica nueva o mejorada con la bifurcación principal u otras bifurcaciones de característica hasta que la característica tenga el código completo, pase las pruebas de calidad necesarias o satisfaga la DoD. Solo en ese momento se integra (combina) la característica con la bifurcación principal. Por lo tanto, el aislamiento del código y la integración continua están de algún modo en extremos opuestos del “espectro de la integración”.

La habilitación de una nueva característica en una implementación es relativamente fácil y carente de riesgos. Simplemente se activan los conmutadores de característica asociados para que se habilite y esté visible. El esfuerzo para lanzar una nueva característica utilizando las bifurcaciones de característica es mucho más complicado. Se tiene que combinar la característica en la bifurcación principal. Con frecuencia requiere mucho tiempo y es un proceso desafiante.

Eliminación de una característica

En algunos proyectos, tendrá que eliminar o borrar características incompletas. La reversión de conjuntos de cambios individuales para revertir una característica (selección de los cambios) también es complicada, trabajosa y puede requerir una reordenación de código importante.

Es imperativo aislar las características de la bifurcación principal hasta que decida lanzar esas características. En cualquier caso, la reversión de una característica de una versión justo antes de su lanzamiento es arriesgada y propensa a errores. Con la utilización de conmutadores de característica, se comprueba todo el código para todas las características en la bifurcación principal. Los conmutadores de característica simplemente ocultan o deshabilitan las características seleccionadas del tiempo de ejecución o la versión.

Elecciones de implementación

Hay varios enfoques para persistir el estado de los conmutadores de característica de una aplicación. Existen dos enfoques bastante directos:

  1. Utilizar la configuración de la aplicación para definir los conmutadores de característica (implementados en el archivo XML de configuración de la aplicación cuando se compila la aplicación).
  2. Almacenar los conmutadores de característica como filas en una tabla de base de datos.

Definir conmutadores de característica No solo es más fácil definir conmutadores de característica en el archivo de configuración utilizando el Diseñador de configuración, sino que no hay necesidad de hacer nada en la aplicación para guardar el estado de los conmutadores de característica cuando finaliza la aplicación. El archivo de configuración de ejemplo que se muestra en la Figura 4 define los conmutadores de característica.

This Sample ConfigSettings File Stores Feature Toggle State for the Windows Calculator
Figura 4 Este ejemplo de archivo ConfigSettings almacena el estado de los conmutadores de característica para la calculadora de Windows

Almacenar conmutadores de característica como filas de base de datos Para utilizar una tabla de base de datos de conmutadores de característica para almacenar el estado de los conmutadores de característica, la aplicación requerirá dos archivos de configuración. El archivo de configuración CommonSettings define las opciones utilizadas por la aplicación. El archivo de configuración DatabaseSettings controla si los conmutadores de característica están definidos y persisten en una tabla de base de datos (cuando son True) o en un archivo de configuración (cuando son False). El archivo FeatureToggleSettings proporciona los nombres para cada conmutador de característica que almacenará en la base de datos (vea la Figura 5).

Feature Toggle Names Stored in the Database Table As Rows
Figura 5 Nombres de conmutadores de característica almacenados en la tabla de base de datos como filas

El enfoque utilizado en el ejemplo de calculadora de Windows es crear dinámicamente filas de conmutadores de característica. Cuando la aplicación se ejecuta por primera vez, la tabla estará vacía. En tiempo de ejecución, todos los nombres de conmutadores de característica se comprueban para ver si están habilitados. Si aún no hay ninguno en la tabla, la aplicación los agregará. La tabla de ejemplo FeatureToggle de la Figura 6 muestra todas las filas de conmutadores de característica agregadas.

FeatureToggle Table After Initial Run
Figura 6 Tabla de conmutadores de característica después de la ejecución inicial

Conceptos independientes de la implementación

Cuando se utiliza un conmutador de característica para deshabilitar una característica, el código de la aplicación oculta o deshabilita los controles en función del valor del conmutador de característica (True/False) asociado a esa característica. Puede elegir ocultar completamente de la IU las características en desarrollo o mostrar la característica como deshabilitada. Cuando lance la característica, estará visible y habilitada.

La Figura 7 muestra la calculadora de Windows con solo la característica de teclado visible y habilitada. Las funciones de memoria y las funciones avanzadas están visibles, pero deshabilitadas.

Windows Calculator with Keypad Feature Visible and Enabled, and the Memory and Advanced Functions Features Visible and Disabled
Figura 7 Calculadora de Windows con la característica de teclado visible y habilitada y las características de memoria y funciones avanzadas visibles y deshabilitadas

El primer paso de esta aplicación de ejemplo crea una nueva base de datos FeatureToggleDemo, y luego se crea una tabla FeatureToggle simple. Al descargar la aplicación de ejemplo, encontrará tres archivos SQL para: la creación de la base de datos FeatureToggle, la creación de la tabla FeatureToggle y la creación de dos procedimientos almacenados utilizados por la aplicación para cargar valores de la tabla FeatureToggle y guardarlos en ella.

Después de crear la tabla FeatureToggle, no hay necesidad de agregar ninguna fila FeatureToggle antes de ejecutar la aplicación por primera vez. La aplicación utiliza una biblioteca de clases FeatureToggle para encapsular toda la lógica de la aplicación para acceder y actualizar los conmutadores de característica.

El código siguiente muestra campos privados utilizados para contener el estado de los conmutadores de característica:

private Boolean _IsKeyPadFeatureEnabled = false; private Boolean _IsKeyPadFeatureVisible = false; private Boolean _IsMemoryFeatureEnabled = false; private Boolean _IsMemoryFeatureVisible = false; private Boolean _IsAdvancedFeatureVisible = false; private Boolean _IsAdvancedFeatureEnabled = false;

El código de la figura 8 muestra cómo establecer campos privados de valores de conmutadores de característica en el archivo ConfigSettings.

Figura 8 Valores de conmutador de característica almacenados en un archivo ConfigSettings

private void GetFeatureTogglesFromSettings() { _IsKeyPadFeatureEnabled = Properties.ConfigSettings.Default.KeyPadFeatureEnabled; _IsKeyPadFeatureVisible = Properties.ConfigSettings.Default.KeyPadFeatureVisible; _IsMemoryFeatureEnabled = Properties.ConfigSettings.Default.MemoryFeatureEnabled; _IsMemoryFeatureVisible = Properties.ConfigSettings.Default.MemoryFeatureVisible; _IsAdvancedFeatureEnabled = Properties.ConfigSettings.Default.AdvancedFeatureEnabled; _IsAdvancedFeatureVisible = Properties.ConfigSettings.Default.AdvancedFeatureVisible; tbMode.Text = Constants.configSettings; }

El código de la Figura 9 muestra cómo establecer campos privados de valores de conmutadores de característica almacenados en la tabla de base de datos FeatureToggle.

Figura 9 Establecer campos privados de valores de conmutadores de característica almacenados en una tabla de base de datos

private void GetFeatureTogglesFromStore() { _IsKeyPadFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.KeyPadFeatureEnabled); _IsKeyPadFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.KeyPadFeatureVisible); _IsMemoryFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.MemoryFeatureEnabled); _IsMemoryFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.MemoryFeatureVisible); _IsAdvancedFeatureEnabled = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.AdvancedFeatureEnabled); _IsAdvancedFeatureVisible = FeatureToggles.FeatureToggles.IsEnabled( Properties.FeatureToggleSettings.Default.AdvancedFeatureVisible); tbMode.Text = Constants.databaseSettings; }

El código de la Figura 10 muestra cómo la aplicación evalúa los conmutadores de característica y establece las propiedades Visible y Enabled de la característica de calculadora de Windows utilizando métodos contenedor.

Figura 10 Utilización de métodos contenedor para establecer las propiedades Visible y Enabled de la calculadora de Windows

private void EvaluateFeatureToggles() { this.tbVersion.Text = Properties.CommonSettings.Default.Version; if (Properties.CommonSettings.Default.DatabaseSettings) { GetFeatureTogglesFromStore(); } else { GetFeatureTogglesFeatureToggleFromSettings(); } if (_IsAdvancedFeatureEnabled) { _IsAdvancedFeatureVisible = true; } SetAdvancedFeatureEnabled(_IsAdvancedFeatureEnabled); SetAdvancedFeatureVisible(_IsAdvancedFeatureVisible); }

El siguiente código muestra una función de contenedor para ocultar o mostrar elementos de IU asociados a la característica de funciones avanzadas:

private void SetAdvancedFeatureVisible(bool state) { this.btnBkspc.Visible = state; this.btnSqrt.Visible = state; this.btnPercent.Visible = state; this.btnReciprocal.Visible = state; this.btnPlusMinus.Visible = state; }

La calculadora de Windows aprovecha la biblioteca de clases reutilizables para encapsular todo el proceso asociado a la tabla FeatureToggle. Con esta biblioteca de clases, el código que utiliza el archivo ConfigSettings es casi idéntico al código que utiliza una tabla de base de datos FeatureToggle.

Resumen

La ventaja de los conmutadores de característica es que las características nuevas o mejoradas se comprueban en la bifurcación principal, por lo que se pueden integrar continuamente y probar con el código base existente en tiempo de compilación. Anteriormente, el código de características nuevas o mejoradas no se integraba por lo general con el código base hasta cerca del día del lanzamiento, lo que es arriesgado, exigente y peligroso. Tanto los conmutadores de característica como las bifurcaciones de característica son enfoques viables que se pueden utilizar para lograr una versión estable con solo características completadas que han pasado las pruebas de control de calidad necesarias. La opción de utilizar una u otra dependerá de sus necesidades y de los procesos de desarrollo que lleve a cabo.

Bill Heys es consultor jefe de ALM en Design Process and Solutions. Anteriormente había sido consultor principal de ALM en Microsoft. Es miembro de Microsoft Visual Studio ALM Rangers, desarrollador jefe en las ayudas de Rangers Branch and Merge y contribuye en las versiones de las guías de Ranger Version Control. Lo encontrará en bill.heys@live.com.

Gracias a los siguientes expertos técnicos por revisar este artículo: Michael Fourie (consultor independiente), Micheal Learned (Microsoft), Matthew Mitrik (Microsoft) y Willy-Peter Schaub (Microsoft)