Cuando publiqué «El ciclo de vida de los experimentos», un antiguo compañero de trabajo en rumbo.es y lastminute.com al que aprecio y valoro mucho como profesional, Javier LopezSoftware consultant en ThoughtWorks – me hizo el siguiente comentario:

No me lo pensé dos veces y le propuse que escribiera un artículo con su visión y experiencia, como un referente en el desarrollo de software, así que todo lo que viene a continuación es de su cosecha. Gracias compañero por ayudarme 🙂


“La experimentación consiste en el estudio de un fenómeno, reproducido generalmente en un laboratorio repetidas veces en las condiciones particulares de estudio que interesan, eliminando o introduciendo aquellas variables que puedan influir en él. La experimentación es una de las fases o etapas del método científico.”

Wikiquote

La experimentación en ciencias se utiliza para obtener información de un fenómeno y validar o rechazar una hipótesis. Lo queramos o no, si lanzamos un producto al mercado vamos a experimentar con él. Desde el punto de vista de la inversión, si fracasa perdemos la inversión, si funciona generamos valor (un escenario binario o todo o nada). En software esto es un poco equivalente a subir una feature completa a producción y ver cómo los usuarios la acogen. Teniendo esto en cuenta, ¿es necesario que subamos una feature a producción para poder medirla?.

Batch size

Una de las maneras más fáciles para reducir el riesgo de nuestra feature es reducir su scope. Debe seguir siendo medible y debe seguir sirviéndonos de proxy de la feature final. Solemos tender a pensar que subimos a producción un conjunto de features (una o muchas) de una sola vez. El batch size (Batch size is the size, measured in work product, of one completed unit of work) en ese caso sería nuestra release. 
En el caso de que pensáramos que nuestra feature es nuestro batch size, una vez desplegada en producción nos encontraríamos con estos escenarios:

  • La feature triunfa. Perfecto, hemos acertado a la primera, ¡a contar el dinero!.
  • La feature fracasa. Debemos quitarla rápidamente de producción porque nos hace perder dinero.
  • El experimento no es concluyente. En este caso debemos o ser conservadores o tirarnos a la piscina. Si somos conservadores debemos quitar la feature de producción.

Aquí nos sale otro concepto interesante que es el de poder desactivar una feature rápidamente si no cumple nuestras expectativas. Nuestro proceso de desarrollo entra en juego, si por ejemplo tardamos una o dos semanas en subir a producción una nueva versión de nuestro producto, no podremos reaccionar al fracaso rápidamente y perderemos mucho dinero. Podríamos hacer rollback, pero si hemos subido a producción un montón de features en esa versión de la aplicación, entonces las desactivamos todas, y por tanto es peor el remedio que la enfermedad.

El batch size es la clave, si es pequeño nuestras reacciones son rápidas, de lo contrario serán lentas. La feature tal vez no sea el mejor mapping del batch size, en realidad una feature está compuesta de múltiples commitsCommits frecuentes, pequeños y con la capacidad de subirlos a producción de forma automática, para tener menores costes a la hora de reaccionar ante un problema. 
Aquí estarás pensando, sí claro pero qué pasa con la calidad, si subo a producción commits de forma automática introduciré muchos bugs.

Calidad de software

“Eliminate the need for mass inspection as a way to achieve quality by building quality into the product in the first place. Require statistical evidence of built-in quality in both manufacturing and purchasing functions.”

Deming’s Principle of Management n. 3

Este principio de management de Deming resume perfectamente el problema de intentar dar calidad a un producto a través de la revisión manual del mismo. Revisar que un producto o feature tenga la calidad necesaria no debería ser un paso bloqueante realizado por una tercera persona (no el desarrollador) para poder subir a producción. La calidad del producto debería estar en la génesis del mismo, eso reducirá las posibilidades de introducir bugs en él y también será más mantenible. 

Si un desarrollador solo piensa en hacer que su feature funcione entonces la calidad dependerá solo de los revisores (QA, code reviewer) que no han participado en el desarrollo. Estamos de alguna manera añadiendo burocracia para asegurar la calidad. Este simple hecho aumentará el WIP (work in progress) de nuestro equipo de desarrollo. Aumentar el WIP supone aumentar los costes de nuestro desarrollo y además no podremos reaccionar tan rápido si hay algún problema con nuestra feature.

Si seguimos el anterior principio, entonces deberíamos introducir prácticas que aseguren la calidad durante el desarrollo como son:

Por otro lado, en un equipo no estamos solos y otros pueden tocar en el código de manera simultánea, con lo cual debemos tener algún sistema para coordinarnos. Si nos damos cuenta de que tenemos un conflicto con otro compañero cuando hemos acabado nuestra feature,  el coste de arreglarlas (la mía y la de mi compañero) será grande, si lo hacemos cada vez que intentamos subir un commit el coste de arreglar el conflicto ahí es mucho menor (otra vez el batch size). Esto nos lleva a la conclusión de que integrar nuestro código continuamente con el código de nuestros compañeros es más barato (Continuous Integration).
Desarrollar usando esas técnicas dotará a nuestro producto de calidad y seremos rápidos subiendo cambios a producción (time-to-market), es decir, entregando valor continuamente a nuestros clientes y como consecuencia de esto aceleramos la capacidad de generar ingresos tempranos.

Medir nuestra feature

Experimentamos para validar una hipótesis, luego debemos establecer KPIs y thresholds para saber si la hipótesis queda validada o no. Necesitamos tener también en cuenta el tiempo en saber si la feature merece la pena o no. Si necesitamos esperar un mes para ver las ventas que hemos realizado y todo ha ido fatal, hemos perdido muchísimo dinero (feedback rápido).

Para minimizar aún más los riesgos, nuestro sistema podría ofrecer esa feature a algunos clientes no a todos y compararla con el escenario en el que la feature no se ve (A/B testing).Si nuestro sistema es capaz de medirse y hacer A/B testing necesitará tener en el código tanto la feature A como la B y activarla o desactivarla según unas condiciones.
Esto irremediablemente te lleva a utilizar en el desarrollo feature flags y branch by abstraction (si quieres indagar más CI/CD developers perspective).

Resumen

  • Commits pequeños:
    • Integrar constantemente (CI)
    • Desplegar a producción de forma automática los commits (CD)
  • Testear cada commit con TDD que además nos permitirá mejorar nuestra calidad
  • Revisar el código mientras los desarrollamos con Pair programming
  • A/B testing:
    • Definir hipótesis y ser capaces de medirlas con KPIs
    • Branch by Abstraction
    • Feature flags

La mejor manera de aprender cómo amoldar el desarrollo a la experimentación es también experimentar alternativas a cómo estamos desarrollando y ver si obtenemos mejores resultados. 

Imagen destacada pertenece a Foto de Negocios creado por ArthurHidden – www.freepik.es