La productividad de un equipo de ingeniería es desde mi punto de vista muy muy complicada de medir, tanto que en muchas ocasiones lleva usar métricas que son más perjudiciales que otra cosa, por ejemplo: número de pull requests, tickets cerrados, o story points.
Ahora que sea complicado no significa que debamos simplemente no hacer nada. Hay muchas cosas que podemos hacer para entender cómo es la productividad y así mejorarla. Y resulta que medirla es complicado pero no lo es medir lo qué dificulta la productividad (incidentes, alertas, workarounds, patches, etc) y tampoco lo es medir prácticas que sabemos que contribuyen a la productividad gracias a informes como DORA.
Por último siempre nos quedará atar la productividad a métricas de negocio, aunque es complicado y dependerá también de otros factores, por ejemplo producto, imagina apostar por mejorar la conversión en el checkout un 20% y que no tengamos éxito no por cómo ha trabajado el equipo sino porque la hipótesis estaba mal y los cambios en el producto no han tenido el efecto deseado.
En esta newsletter voy a hablar de las dos primeras, identificar cosas que entorpecen la productividad y métricas o prácticas que sabemos que contribuyen a mejorarla.
Una forma de definir la productividad de un equipo de ingeniería vendría dada por cómo es el flujo de valor, es decir, lo que tardamos en poner valor delante del cliente. Así que una forma clara de mejorar la productividad es reducir todo lo que nos frene sacar cosas cuanto antes posible y dentro de unos estándares de calidad, así como hacer incrementos pequeños en lugar de grandes releases.
El objetivo es iterar rápido para validar nuestras ideas antes y que eso nos permita corregir el rumbo y aportar valor más rápido. Los informes (DORA) demuestran de forma consistente que las organizaciones que despliegan con mayor frecuencia y mantienen tiempos de entrega más cortos son mucho más competitivas y contribuyen más a llegar a los objetivos de negocio.
De ahí que cosas como continuous delivery o continuous deployment sean un claro indicativo de productividad. Porque exigen que tengas montada una estructura/organización que te permita poner cada commit en producción sin pasar por procesos de “release”, “fase de testing”, “manual deployment “, etc. Además de una capacidad para testear en producción (canary releases, feature flags, rollbacks rápidos, etc).
Es decir, tenemos que intentar siempre reducir el feedback loop.
Un día normal un developer pasa buena parte del tiempo esperando por herramientas (compilar, tests, ci) y por gente (Code Reviews asíncronas, ayuda de algún compañero, product manager, etc), esto frena o reduce la velocidad a la que hacemos progreso y repercute en el valor que aportamos. Al final este tipo de procesos provoca bastantes cambios de contexto, así cómo retrabajo debido a malentendidos, cambios de código debido a la code review asíncrona, e incluso cambios provocados a haber avanzado sin tener la respuesta… incrementando el tiempo para entregar valor.
Ésto también es crítico para la satisfacción del developer, cuando el feedback loop es lento lleva a frustración, dado que pasan buena parte de su tiempo esperando o cambiando de tareas mientras que pasan los tests o esperan por una review. Y esto empeora ya que cuando los tests o la review terminan la gente tiende a volver a la tarea anterior, incrementando el coste de cambiar de tarea y el tiempo para entregar valor.
Así que una de las cosas que podemos empezar a hacer es medir estos ciclos y así encontrar donde tenemos cuellos de botella, y con está información cambiar procesos y/o prácticas que nos lleven a mejorar. Por poner algún ejemplo, pasar de hacer code reviews asíncronas a otro tipo de code reviews, por ejemplo síncronas (al terminar de programar avisas a una compañera para que se siente contigo y lo revisáis juntas) o continuas (pairing, mob). O eliminar las típicas fases de QA o de despliegue dónde “pasas” tu código para que otros lo validen o lo suban a producción, algo que todavía genera muchos de los problemas mencionados.
En el informa dora se recomiendan 4 métricas (bueno 5 ahora) para medir cómo de eficiente es un equipo, lo que lleva cómo ellos indican a alcanzar los objetivos de negocio.
Deployment Frequency: Mide cómo de frecuente es desplegar código en producción. Esta métrica se correlaciona con la velocidad y la calidad, mide cómo de rápido un equipo es capaz de sacar nuevas features, bug fixes, etc..
Normalmente una velocidad alta también está relacionada con el uso de buenas prácticas, continuos delivery, trunk based development, features flags, etc.Change Failure rate. Es el porcentaje de deploys que provocan un fallo en producción. Esto suele ser indicativo de la calidad del código, de los tests que tienes, etc. Es decir, tu objetivo es reducirlo. Esto tiene un coste económico muy claro ya que tiene una relación directa con incidentes que afectan a usuarios. Además del coste de sacar/desactivar de producción algo y el coste en estrés que suelen generar los incidentes.
Para obtener esta métrica se suele medir el número de rollback, el número de incidentes, etc.Time to restore the Service. El tiempo que tardamos en recuperar el sistema después de un fallo en producción. Es fácil imaginarse la importancia de esta métrica: satisfacción de los clientes, reducir costes económicos (por ejemplo por no dar un servicio), reducir el estrés del equipo de ingeniería (si tienes un sistema que permite detectar de manera inmediata un incidente y procesos para hacer rollback de manera rápida, reduce el miedo a salir a producción y el estrés de gestionar un incidente).
Para medirlo es tan fácil como contar desde que ocurre un incidente hasta que se resuelve. Hay hasta herramientas que esto te lo automatizan en gran medida, incident.io, pagerduty, etc, bueno siempre y cuando tengas un buen sistema de monitorización montado.Lead time for Changes. Mide el tiempo que tardamos desde el primer commit a llevarlo a producción.
Source: https://www.usehaystack.io/blog/lead-time-cycle-time-change-lead-time
Esta métrica es parte de otras dos, como vemos en la imagen y creo que las tres nos dan una mejor visión de cómo trabaja un equipo.
Tener mucho changed Lead time puede ser una señal de varias cosas:Que las MRs pasan mucho tiempo en review.
Que trabajamos en chunks muy grandes, lo que lleva a pull requests grandes y complejas. Lo incrementa el riesgo de que ese código nos dispare en el pie (bugs, tiempo de encontrar un problema, de hacer cambios, etc)
Que el despliegue es complejo y lleva tiempo.
etc.
Cycle time suele ser señal de tener mucho WIP, demasiadas cosas abiertas. Y Lead time de tener un backlog grande o descontrolado (no bien priorizado, tener muchos bugs, no hacer triage de los tickets, etc).
Pero hay muchas más cosas que podemos medir que nos pueden ayudar a identificar como de productivos y eficientes somos:
Incidentes.
Alertas que requieren atención inmediata.
CI Pipeline time.
Flaky tests.
Code Reviews time.
Cognitive Load
Algo que contribuye en gran medida a la productividad de una ingeniera es la carga cognitiva que tiene. Pero, ¿qué significa eso? Pues todo lo que necesitan comprender y dominar para poder completar una tarea:
Lenguaje.
Framework.
Prácticas (testing, monitoring, observability, etc).
Herramientas.
Código (complejidad de los sistemas, deuda técnica).
Conocimiento del dominio.
Todo esto juega un papel fundamental en la velocidad a la que entregamos valor. Por eso es importante que muchas de estas cosas sean facilitadas/abstraídas en la medida de lo posible, por ejemplo, no necesitamos construir desde cero cómo hacer monitoring para cada tarea. Seguramente usaremos una herramienta como prometheus y una abstracción en el lenguaje o framework que nos permite enviar métricas sin conocer en detalle cómo llegan a prometheus.
Ahora bien, una de las cosas que más contribuyen a la carga cognitiva es el scope del equipo. Es decir, el conocimiento del dominio.
Esto abarca desde el conocimiento de las funcionalidades de las que el equipo es responsable a el código, sistemas y arquitectura de las mismas. A más grande es el scope más complejo es hacer un mapa mental de cómo funciona todo a nivel de producto pero también a nivel de código. Esto se complica aún más en función de cómo de sano sea el software, a más deuda técnica y más enmarañado esté el sistema más complicado será comprenderlo pero aún más importante, más probable será que un cambio en el sistema tenga efectos no deseados. Esto a su vez lleva a tener más KTLO, lo que reduce la velocidad a la que entregamos valor porque tenemos que pasar buena parte del tiempo achicando agua.
KTLO
He mencionado en esta newsletter varias veces el KTLO, así que voy a explicarlo porque es una de esas cosas que muy pocas empresas entienden, miden y que no son conscientes de cómo afectan a la productividad. El acrónimo viene de Keeps the Lights on, es decir, lo que tenemos que hacer para que el sistema siga funcionando.
KTLO incluye todo el trabajo digamos oscuro. Una forma muy sencilla de entender lo qué es sería pensar en esas situaciones donde vuestros equipos no paran de currar pero no se llega a cerrar/entregar lo que habías planificado, no se llega a los objetivos, parece que no llegáis a todo… tenéis la sensación de achicar agua todo el tiempo. Esto es típicamente una señal de KTLO muy alto.
En él incluimos cosas como atender On-call alerts, incidentes, corregir bugs, problemas que requieren atención inmediata (por ejemplo requests de clientes), etc.
KTLO no es Deuda técnica aunque la deuda técnica puede contribuir y mucho a ello, por ejemplo, un código muy complejo, difícil de testear y frágil o una arquitectura compleja o despliegues poco seguros son más probable que provoquen bugs e incidentes. Pero piensa en el KTLO como todas esas actividades/tareas que haces de manera diaria que no forman parte del desarrollo de nuevas funcionalidades.
Un problema añadido es que es difícil de visibilizar y por eso motivo muchas veces este trabajo no forma parte de los sprints, no se prioriza ni se considera y es a su vez común que los mánagers/leads de los equipos no paran de escuchar que “el delivery” es lento a pesar de que el equipo trabaja como sino hubiera mañana.
Así que tenemos que medir el KTLO para poder explicar el tiempo real que la gente dedica a nuevas funcionalidades, pero sobre todo para entender dónde se va el tiempo y poder solucionarlo.
El objetivo no es tener KTLO cero, eso no es posible, piensa que siempre nos tocará hacer patches de seguridad, hacer upgrade de dependencias, migraciones, corregir bugs, responder a dudas, etc. El objetivo es tener un nivel bajo de KTLO, se suele indicar como un objetivo razonable por debajo del 20% de la capacidad del equipo.
No hace falta que hagáis nada mágico para medir esto, es mucho más fácil, por ejemplo en Tinybird tenemos a una persona por equipo haciendo KTLO y lo que vemos es si es suficiente para achicar agua, en algunos equipos vemos que tenemos a 2 personas o sino no llegamos. Eso ya es un claro indicativo de que tienes que trabajar en reducirlo, pero además es suficiente para medirlo y visualizarlo, si tienes a dos personas en el equipo con KTLO y el equipo es de 5 pues el KTLO es un 40%. Por poder podríamos medirlo contando el tiempo total que dedicamos a cosas que no son KTLO menos el tiempo total que tenemos en una unidad de tiempo, sprint o lo que sea. Pero vamos que nos valdría incluso con preguntar a la gente del equipo cuánto tiempo han dedicado a KTLO.
Lo que sí es importante es que entiendas que es muy crítico visualizar ésto si quieres identificar de verdad los problemas que frenan vuestra productividad, y conseguir que se prioricen.
Algunos trucos para reducir KTLO:
Buena documentación para evitar requests de clientes o de otros equipos sobre cómo funcionan las cosas.
Automatización. Todas aquellas tareas que requieran de intervención manual, por ejemplo: migraciones de DB, recuperación de datos, deploys manuales, ops como cambiar el tráfico a otro server para desplegar en el otro.
Reducir deuda técnica. Pero no sin ningún criterio, sino que tenemos que identificar puntos débiles dentro del código fuente. Llevar un tracking de qué componentes tienen más bugs, incidentes relacionados y priorizar arreglar esas partes.
Invertir en buenas herramientas y buena documentación (runbooks) para que cuando haya que intervenir ante un incidente, una alerta, sea fácil entender el problema y restaurar el sistema.
¿Corregir bugs? Corregir ayuda en algunos casos, especialmente en aquellos que son reportados y provocan que alguien del equipo tenga que echar una mano, por ejemplo para hacer un workaround o para resolver una incidencia o consecuencia (e.g recuperar datos). Pero solo corregir bugs no es suficiente, esto es achicar agua en un bote con un agujero.
Que no se entienda esto como no corrijamos bugs, nada que ver. Es necesario no solo por KTLO, también por calidad. Pero piensa que si dedicas mucho tiempo a corregir bugs, pongamos que dos personas de 5 que tiene el equipo cada semana, lo que te pasa en realidad es que mínimo tienes el KTLO al 40%, así que lo que tienes que buscar es la raíz de esos bugs y así reducir la cantidad y velocidad a las que se crean.
Para terminar que creo que para una newsletter ya va un texto largo, una cosa importante a tener en cuenta es que no se trata de optimizar las cosas para tener a todo el mundo ocupado, sino de optimizarlas para entregar valor antes. Por eso el énfasis en trabajar Lean y tener procesos y prácticas (e.g reviews síncronas, continuous delivery, automatización, infra as code, etc) que permitan optimizar el flujo.
Este video explica muy bien porqué es necesario trabajar tanto en sacar partido a los recursos como optimizar el flujo.
Una última cosa, esta vez de verdad, quiero compartir este gráfico que puede ayudar a medir la productividad.
https://queue.acm.org/detail.cfm?id=3595878
BTW Gracias Eferro por la review y el feedback!