Estimación y Planificación en contextos de Entrega Continua

Cuando una organización y/o equipo pretende comenzar a trabajar en un esquema de entrega continua, se pone un esfuerzo casi exclusivo en cuestiones de automatización lo cual en muchos casos no resulta bien.

Trabajar en un esquema de entrega continua requiere automatización pero también algunas otras cuestiones que son incluso necesarias para poder automatizar. La automatización en un contexto de entrega continua incluye principalmente la automatización de pruebas y de despliegues. Ahora bien, para automatizar pruebas y despliegues es necesario tomar ciertas «precauciones» en términos de arquitectura y diseño. Pero eso no es todo, si queremos trabajar en un esquema de entrega continua, entonces nuestro trabajo de planificación debe estar en línea con ello.

Es muy difícil (por no decir imposible) trabajar en un esquema de entrega continua si cada story/funcionalidad lleva semanas de desarrollo. Es clave que podamos particionar las stories/funcionalidades de forma tal de poder completarlas en un par días. Al mismo tiempo, la entrega continua implica, como su nombre lo indica, entregar continuamente, o sea: (casi) todos los días. Si cada story/funcionalidad lleva semanas, entonces es posible que nuestras entregas sean cada un par de semanas. En cierto modo es como un efecto en cadena: cuando más grandes las stories, más tiempo insume su desarrollo y más tiempo insume su pruebas y más tiempo insume su despliegue y más riesgos enfrentamos, etc, etc.

Desde otras perspectiva, ocurre que cuanto más diferimos la entrega, mayor relevancia toman nuestras estimaciones. Si hacemos esperar a nuestros usuarios/clientes, aumentamos su «ansiedad» y su necesidad de saber cuanto más tendrán que esperar.

Por otro lado, si trabajamos en pequeños incrementos habilitamos la entrega más rápida y continua, lo cual nos saca presión de estimación. Al mismo tiempo, las técnicas y dinámicas de estimación no son precisamente las mismas de cuando pretendemos hacer entregas frecuentes/continuas que cuando apuntamos a entregas esporádicas a mediano y largo plazo.

En línea con todo esto, estoy armando un taller muy práctico sobre diversas técnicas para estimar y planificar en contextos de Entrega Continua. Aún no tengo fecha, pero los potenciales interesados pueden escribirme para que los mantenga al tanto.

#HistoriaDeTrinchera: Planning de una User Story

Recurrentemente hablo con gente que me comenta de sus dificultades para completar el trabajo planificado en la iteración. En muchos de esos casos mi sensación es que el equipo incluye funcionalidades en su iteración sin tener suficientemente en claro su implicancia. Creo que muchos se han ido del extremo de especificar cada detalle de la funcionalidad en un documento tipo especificación de casos de uso, a directamente pasar al otro extremo y escribir un título y nada más. Es por esto que quiero compartir en este artículo el ejercicio que intentamos hacer en mi proyecto actual a la hora de armar nuestro backlog de iteración determinando las funcionalidades que trabajaremos.

Una de las particularidades de nuestro proyecto es que como parte del equipo tenemos una especialista en diseño de experiencia usuario (digo particularidad pero me parece que esto es cada vez más común). A su vez esa especialista es en simultáneo parte de otro equipo que trabaja en forma transversal en el diseño de la experiencia de varios productos de la organización. Es así que las funcionalidades (que usualmente llamamos user stories) se piensan desde un momento muy temprano teniendo presente la experiencia que se quiere ofrecer al usuario. De esta forma, cuando hablamos sobre una funcionalidad en una reunión de planificación generalmente ya contamos con un diseño de pantalla (o tal vez varias) que acompañan la conversación.

De la conversación sobre la user story buscamos esclarecer los siguientes puntos para poder agregarla al backlog de la iteración:

  • El escenario principal de uso y alguno de los escenarios alternativos más importantes. De ser posible, y si la complejidad lo amerita, ahi mismo expresamos estos escenarios en sintaxis Gherkin.
  • Las tareas necesarias para completar la story como ser: codear la pantalla, codear un nuevo servicio, codear componente para conectar con otro sistema, generar los datos de prueba, automatizar la prueba end-2-end, etc, etc
  • La dependencias de otras aplicaciones/apis y estados de las mismas (esa API que debemos consumir ¿ya está disponible en producción? ¿la está consumiendo algún otro equipo?)
  • La necesidad (o no) de hacer que la funcionalidad sea «apagable» o «segmentable». Hay funcionalidades que son simples y de baja criticidad que apenas las terminamos pueden ser liberadas al público en general, pero hay otras que, ya sea por su complejidad o criticidad, se prefiere liberarlas gradualmente a distintos grupos de usuarios. En términos técnicos pretendemos identificar si la funcionalidad debe ser «toogleable».

A medida que vamos viendo cada una estas cuestiones vamos tomando conciencia del tamaño y la complejidad de la funcionalidad y puede que en base a ello decidamos partir la funcionalidad en varios cortes (lo que comúnmente se conoce como slicing).

En algunos casos parte de estas cuestiones se hablan en una reunión de refinamiento que ocure previamente a la planning. A su vez dicha reunión nos permite identificar potenciales blockers para el desarrollo de alguna funcionalidad pedida. En algunos casos también ocurre que la funcionalidad pedida depende de funcionalidades provistas por alguna API desarrollada por otro equipo y que no se encuentra disponible aún o tal vez no provee todo lo que necesitamos. En estos casos en lugar agregar la funcionalidad en cuestión a nuestra iteración, agregamos una tarea de gestión para darle seguimiento a al desarrollo de esa API e incluso hacer algún prueba de concepto como para ir familiarizándonos.

Dos datos adicionales de contexto:

  • En las reuniones de refinamiento no participa necesariamente todo el equipo. Seguro están los especialistas de negocio, la especialista en UX, el facilitador y algunos devs. En general esta reunión dura 1 hora.
  • Las reuniones de planificación tiene 2 partes: una estratégica donde participa todo el equipo y una táctica donde solo participan los técnicos (devs & testers). Entre ambas se van entre 2 y 3 horas.

A partir de lo anterior resulta que para planificar una iteración de 2 semanas este el equipo requiere en total de unas 4 horas de trabajo conjunto.

Algunas de estas cuestiones puede que no coincidan exactamente con lo que recomiendan algunos libros y posiblemente a algunos lectores puede que le resulten impracticables en su propio contexto y lo entiendo. No es mi intención convencer a nadie de trabajar de esta de esta forma, simplemente pretendo compartir lo que a nosotros nos viene funcionando y nos permite entregar software todas las semanas.

Previsibilidad mata velocidad

Completamos la séptima iteración entregando menos de lo que habíamos planificado y eso generó cierto debate en la planning de la octava iteración, llevando incluso a que algunos miembros del equipo quieran replantear la forma de estimación.

Hasta el momento hacíamos lo siguiente:

  • Repasar el backlog candidato determinado por el Product Owner, asegurando que entendíamos cada uno de los ítems
  • Estimar «a ojo» los item que consideramos podríamos llegar a completar en la iteración por comenzar
  • Asignar puntos (1, 2 o 3) a cada uno de los items, principalmente para estar seguros que todos los miembros del equipo teníamos una idea similar de las implicancias/alcance de cada ítem. Importante: estos puntos no los utilizamos para determinar la cantidad de trabajo de la iteración, sino simplemente como un mecanismo de doble validación interna.

Con este mecanismo en la iteración 7 planificamos unos 23 items pero completamos unos 18.

Antes de continuar debo decir que:

  • En la gran mayoría de equipos que he estado involucrado «con problemas de estimación», resultó que en realidad era mucho más grave el problema de ejecución que el de estimación
  • Para equipos comprometidos, auto-organizados y trabajando en iteraciones cortas y con un esquema de continuous delivery no creo que valga la pena estimar «formalmente» con puntos/horas ni nada por el estilo más allá de la sensación del equipo

Dicho todo esto, mientras parte del equipo debatía sobre los ajustes al método de estimación/planificación, me puse a repasar el histórico de iteraciones en el Jira y confirmé mi sospecha viendo unos de los reportes provistos por la herramienta:

El nombre que la herramienta da a este gráfico es «Reporte de Velocidad» el mismo muestra en gris el plan del equipo al inicio de cada iteración y en verde lo efectivamente completado al final de la iteración. Se supone que a partir de este gráfico uno podría deducir una velocidad/capacidad del equipo que puede resultar útil a la hora de planificar.

Analizando este caso particular uno podría decir que este equipo puede entregar alrededor de 18 puntos por iteración. Sin embargo, ese no es el dato más importante de este gráfico para mí.

Lo que me resulta más relevante de este gráfico es la predecibilidad. Puede verse que independiente del número X planificado, este equipo entrega consistentemente con un desvió promedio de ~18 %, siendo este desvío en ocasiones positivo (se entrega más de lo planificado) y en ocasiones negativo (se entrega menos de lo planificado). Más aún, si eliminamos del cálculo la iteración 4 que fue particularmente corta en términos de días laborales (por feriados) y que tuvo una variación de equipo (se sumo una persona), el desvío promedio cae por debajo del 15%. Personalmente creo que es un grado de predecibilidad muy bueno, sobre todo si consideramos que el equipo tiene la capacidad (tanto a nivel proceso como de infraestructura) de entrega software potencialmente todos los días.

En general prefiero no hablar de la velocidad de un equipo pues creo que puede generar falsas expectativas por la sola terminología. Alguien fácilmente podría tentarse de pedirle al equipo que aumente su velocidad generando así presiones para el equipo. Y ni hablar de quienes pretenden comparar la velocidad de distintos equipos. Es por esto que prefiero no hablar de velocidad como una característica del equipo. Prefiero caracterizar al equipo por cuan predecible es.

Dilemas del Slicing

Veníamos haciendo un muy buen trabajo slicing, en realidad no se si tan bueno pero yo me sentía muy cómodo. Primero definimos las stories, hacíamos alguna apertura en tarea y si nos parecía muy grande/complejo, abríamos una story. Finalmente hacíamos una puntuación a modo de doble validación. En términos de puntuación todas nuestras stories eran 1, 2 o 3.

Pero resulta que en la última planning, nos encontramos con una story puntuada en 5. ¡Recórchilis! Intentamos buscarle la vuelta para partirla pero no lo logramos. Entonces uno de los muchachos sugirió partir la story en front y back, ya que tan front como back son tecnología distintas, repos distintos y artefactos de runtime distintos.

He aquí el dilema:

  • Opción 1: planificar una story demasiado grande.

  • Opción 2: partir la story en dos stories donde cada una en forma independiente no agrega valor.

La opción 2 para mi no era válida, con lo cual decidimos ir por la opción 1. Personalmente me hacía mucho ruido el 5, pero internamente yo estaba convencido que la story estaba más cerca de un 3 que de un 5.

La semana próxima les cuento que tal nos fue.

El problema no está en la estimación

Recurrentemente escucho equipos decir que tienen problemas con la estimación, pero cuando tengo la oportunidad de trabajar con ellos durante un par de iteraciones queda en evidencia que la estimación es solo una pequeña parte del problema. El problema grueso suele estar en la ejecución.

Describo el caso típico: un equipo estima que en una iteración completará una cantidad N de ítems. Al finalizar la iteración resulta que completa Z ítems siendo Z bastante menos que N. Instantáneamente se cree que el equipo estima mal.

Entonces me sumo a la dinámica de trabajo del equipo durante una iteración participando de sus Planning, Review, Retros y Dailies. Una vez más el equipo compromete N ítems pero completa Z ítems (N>>Z), pero adicionalmente a eso detecto las siguientes situaciones que ocurrieron durante la iteración:

  • Se trabajaron a pedido del cliente otros ítems que no eran parte del plan inicial de la iteración
  • También se invirtió esfuerzo en arreglar el servidor de tests que dejó de funcionar debido a un update no planificado
  • Parte del equipo tuvo que participar de una reunión con otro equipo que planea reutilzar algunos de los componentes desarrollados por este equipo
  • Un miembro del equipo enfermó y estuvo en cama 2 días sin poder trabajar.

Todas estas cuestiones fueron realizadas sin modicar el plan/compromiso de la iteración y tampoco fueron registradas en ningún lado. De haberse registrado, la lectura de la iteración sería:

  • Se comprometieron N items
  • De los N items comprometidos se completaron Z (siendo Z menor a N)
  • Adicionalmente se completaron otros A items que no estaban planificados
  • Muchas veces A + Z es mayor o igual a N

El haber trabajado en items nos planificados y no haber gestionado correctamente su inclusión nos indica que hay un claro problema de ejecución.

Luego de haber visto recurremente esta situación he decidido armar un taller de planificación adaptativa y seguimiento de proyectos para intentar ayudar a los equipos con problemas de estimación, planificación y ejecución.

Estabilizando la velocidad

Durante las dos primeras iteraciones decidimos no puntuar las stories con un valor explícito de estimación. Simplemente a la hora de determinar el compromiso de la iteración utilizamos la tantas veces usada técnica de «estimación a ojo de buen cubero». Pero ya en la tercera iteración el cliente nos pidió que puntuáramos las todas las stories del backlog para poder hacer una proyección. Así que eso hicimos, repasamos todo el backlog haciendo una estimación de mano (una variante del famoso planning pocker).

Adicionalmente al comienzo de cada iteración, repasamos los valores asignados a cada story  y de considerarlo necesario los volvimos a estimar.

La semana pasada completamos la sexta iteración y por primera vez entregamos exactamente lo que habíamos comprometido. Hasta entonces siempre habíamos tenido un pequeño delta positivo o negativo.

Comprometido vs. Entregado

Como se puede apreciar en el gráfico precedente la cantidad de puntos entregados por el equipo ha ido en aumento desde la iteración 4. Parte de ese incremento se debe a que las iteraciones 4 y 5 tuvieron días feriados en los que no trabajamos y que hicieron que dichas iteraciones fueran más cortas en términos de días trabajados.

En este momento estamos trabajando en la iteración 7 y el tamaño del compromiso tomado es bastante mayor a las iteraciones anteriores (75 puntos). Esto se debe a que se sumo una nueva persona al equipo.

Al finalizar la iteración 8 saldremos a producción. Yo hubiera preferido salir antes, pero resulta que estamos reemplazando un producto existente y ha sido muy difícil hacer un recorte de funcionalidad que nos permita salir antes sin impactar negativamente en el negocio.

Continuará…