Primeros pasos en nuestra transformación DevOps
5 minutos de lectura

En el segundo capítulo de esta serie - DevOps for the Win, exploramos los pasos iniciales cruciales de un viaje de transformación DevOps. Los primeros pasos de cualquier proceso de transformación suelen ser los más difíciles. En DevOps, la identificación de los pasos iniciales correctos, que sean a la vez impactantes y alcanzables, es clave para impulsar un progreso significativo.

Muchas organizaciones cometen el error de aplicar ciegamente las mejores prácticas sin tener en cuenta sus limitaciones específicas, lo que a menudo conduce a la frustración y a la fatiga por el fracaso. En su lugar, es necesario un enfoque más estratégico, que identifique los cuellos de botella y los elimine sistemáticamente.

¿Cómo identificar los primeros pasos?

Un poderoso principio para identificar por dónde empezar procede de una investigación publicada hace 30 años en The Goal: A Process of Ongoing Improvement, de Eliyahu M. Goldratt. La idea es sencilla: identificar el principal cuello de botella, el factor limitante que restringe el rendimiento del sistema. En nuestro caso, esto quedó claro cuando vimos que el trabajo se acumulaba en el equipo de desarrollo. Las tareas se iniciaban pero no se completaban, y el trabajo pendiente seguía creciendo.

Para descubrir las causas, organizamos sesiones de profundización con equipos de desarrollo, responsables técnicos y jefes de producto. Estos debates sacaron a la luz varios problemas clave:

  • Los equipos asumían nuevas tareas antes de completar las existentes.
  • No existían criterios claros de finalización de tareas: lo que los desarrolladores consideraban "hecho" a menudo difería de las expectativas de las partes interesadas.
  • No había medidas objetivas de calidad antes de dar por terminado el trabajo, lo que provocaba defectos y repeticiones.
  • Las frecuentes reasignaciones perturbaban la estabilidad del equipo, provocando ineficiencias.

Establecer equipos estables

Una de las primeras medidas correctoras fue reestructurar los equipos para dotarlos de coherencia y concentración. En lugar de tratar a grupos de individuos como grupos de trabajo ad hoc, formamos equipos estables y duraderos con una propiedad claramente definida.

La creación de algunos equipos, como los de desarrollo, fue relativamente sencilla. Sin embargo, la organización de equipos de apoyo, como los de infraestructura, gestión de proyectos, gestión de productos y análisis empresarial, resultó más complicada. Pasamos por varias iteraciones hasta encontrar las combinaciones adecuadas.

Siguiendo el principio de pensar primero en equipo descrito en el libro Team Topologies de Matthew Skelton y Manuel Pais:

  • Se crearon equipos pequeños y autónomos (de 4 a 7 miembros) para fomentar la responsabilidad y una profunda experiencia en la materia.
  • Se eliminaron las dependencias entre equipos asegurándose de que las personas estuvieran totalmente asignadas a un único equipo.
  • Se perfeccionaron las estructuras de los equipos, sobre todo en funciones de apoyo como infraestructura y gestión de productos, para optimizar el flujo.

Herramientas de visibilidad y gestión

Una vez estructurados los equipos, pasamos a Azure DevOps para la gestión de backlogs y trabajo. Una plataforma unificada habilitada:

  • Mejor visibilidad del trabajo para que los equipos pudieran seguir el progreso de forma transparente.
  • Definiciones normalizadas de "hecho" para alinear las expectativas en todas las funciones.
  • Mejora de la gestión de la cartera de proyectos pendientes, reduciendo las desviaciones del alcance y los conflictos de priorización.

Aplicación de métricas de calidad objetivas

Para resolver el problema de la falta de claridad de las medidas de calidad antes de marcar las tareas como "listas para la prueba", integramos una herramienta de análisis estático del código, que proporciona información objetiva sobre:

  • Cobertura del código
  • Vulnerabilidades de seguridad
  • Código olores

También hemos mejorado nuestra definición de "Terminado" para que las comprobaciones de calidad sean un paso obligatorio antes de marcar los elementos de trabajo como terminados.

Gestión del trabajo en curso (WIP)

Uno de los cambios más impactantes fue la supervisión y limitación del trabajo en curso (WIP). Un WIP elevado indicaba cuellos de botella, us de forma proactiva las áreas en las que el trabajo se estancaba.

Este enfoque sistemático, arraigado en Las Topologías del Objetivo y del Equipo, sentó las bases de la mejora continua, reduciendo las dependencias y mejorando la rendición de cuentas.

En nuestro proceso de transformación DevOps, una de las conclusiones más importantes fue que, tras las mejoras iniciales, la principal limitación para el flujo pasó a ser el diseño del software, concretamente la capacidad de prueba de nuestro código. Después de abordar los cuellos de botella iniciales mejorando la configuración del equipo, definiendo una «definición de terminado» e implementando el análisis de código, nos dimos cuenta de que el trabajo se acumulaba durante la fase de pruebas. El código desarrollado por los equipos scrum a menudo esperaba en fila para ser probado por los QA dentro de los mismos equipos scrum.

Abordar el próximo cuello de botella: La brecha de las pruebas

Una vez resueltos los cuellos de botella iniciales, surgió una nueva limitación: los retrasos en las pruebas. Mientras las tareas de desarrollo avanzaban con eficacia, las pruebas se convertían en un obstáculo que impedía acelerar las versiones. Tras una investigación, identificamos los principales problemas que ralentizaban el proceso:

  • Dependencia de las pruebas manuales: La mayoría de las pruebas se ejecutaban manualmente, lo que provocaba bucles de retroalimentación lentos y retrasos en la detección de defectos.
  • Dependencia de la interfaz de usuario en las pruebas: Como los componentes de interfaz de usuario solían ser los últimos en completarse, las pruebas no podían empezar hasta bien avanzado el ciclo de desarrollo.
  • Falta de automatización proactiva: Las pruebas automatizadas, como las pruebas de interfaz de usuario basadas en Selenium, solo se escribían después de las pruebas manuales, lo que limitaba su eficacia en las primeras fases de validación.

Pasar a enfoques basados en pruebas

Para acabar con este cuello de botella, dimos prioridad a las pruebas unitarias y de API sobre las pruebas de interfaz de usuario. El cambio requirió cambios fundamentales en la mentalidad de desarrollo y el diseño del software:

Mejoras en las pruebas de la API

Para que las pruebas de la API sean eficaces:

  1. APIs bien definidas: APIs ser sencillas, estar bien documentadas y estar disponibles desde el principio de la fase de desarrollo, de modo que los evaluadores pudieran crear casos de prueba de forma proactiva.
  2. Evitar la base de datos como punto de integración:
    • El uso de bases de datos como punto de integración entre equipos creaba dependencias que ralentizaban las pruebas.
    • La creación de casos de prueba requería configurar bases de datos con datos complejos, lo que aumentaba el tiempo de configuración y limitaba la capacidad de probar múltiples escenarios.
    • Al pasar a una integración basada en API (principalmente REST sobre HTTP y, más recientemente, GraphQL), redujimos significativamente los retrasos y complejidades causados por las dependencias de las bases de datos.

Este cambio permitió un progreso más rápido en la automatización de los casos de prueba para APIs, lo que demostró que centrarse en diseños que dan prioridad a las API mejoraba tanto la capacidad de prueba como la eficiencia.

Reforzar las prácticas de pruebas unitarias

Las pruebas unitarias planteaban un reto mayor:

  • Progreso rápido, luego teatro de cobertura: Al principio, logramos altos niveles de cobertura del código, pero las revisiones del código revelaron que muchas pruebas unitarias eran superficiales, escritas sólo para cumplir los objetivos de cobertura. Estas pruebas no comprobaban funcionalidades significativas, no cubrían escenarios de fallo ni validaban casos extremos.
  • Cambio de mentalidad: Los desarrolladores tenían que comprender el valor de las pruebas unitarias, no solo para mejorar la calidad del código, sino también para acelerar el desarrollo detectando los problemas en una fase temprana.

Retos a la hora de escribir código comprobable

El mayor obstáculo para la eficacia de las pruebas unitarias era la falta de comprobabilidad en el propio código base. Los principales problemas eran:

  • Funciones grandes y monolíticas.
  • Componentes estrechamente acoplados.
  • Escasa separación de las preocupaciones.
  • Abstracción insuficiente.

Estos problemas dificultaban el aislamiento y las pruebas eficaces de las unidades individuales. Para solucionarlo:

  1. Directrices proporcionadas: Compartimos buenas prácticas sobre:
    • Selección de funciones para pruebas unitarias.
    • Refactorización del código para mejorar la comprobabilidad.
    • Diseño y uso de mocks para facilitar las pruebas.
  2. Centrado en mejoras incrementales: Se animó a los desarrolladores a realizar cambios pequeños y significativos para mejorar la comprobabilidad con el tiempo.

Progresos, retos y camino por recorrer

En el caso de los productos heredados, la mejora de la comprobabilidad seguía siendo un proceso lento debido a las limitaciones arquitectónicas. Sin embargo, estas acciones no solo pretendían mejorar el código base actual, sino que eran una inversión de futuro:

  • Los desarrolladores adquirieron mejores hábitos, incorporando la comprobabilidad a las nuevas bases de código.
  • Los equipos se volvieron más autosuficientes, reduciendo la dependencia de QA externos QA .
  • La organización evitó repetir errores del pasado, garantizando que los futuros productos fueran más fáciles de mantener y evolucionar.

¿Cuál es la clave? DevOps no consiste en implantar herramientas o listas de comprobación. Se trata de mejorar continuamente el flujo de trabajo, restricción por restricción.

En el próximo capítulo de esta serie, exploraremos el "Diseño para la comprobabilidad". Profundizaremos en cómo la mejora del diseño del software puede eliminar las limitaciones de las pruebas, permitiendo bucles de retroalimentación más rápidos y una mayor calidad del software -primero en las estructuras de equipo, luego en la gestión del flujo de trabajo y, por último, en la comprobabilidad- sentamos las bases para una transformación DevOps sostenible.