sábado, octubre 31, 2009

¡Hay que respetar la build!

sábado, octubre 31, 2009 por Martín

En una de mis últimas empresas, allá por Irlanda (como pasa el tiempo, oiga) teníamos unos 30 desarrolladores. De entre todos estos, unos 10 estaban en Polonia, los demás estábamos en Irlanda. A parte de todo esto teníamos una consultora en el Reino Unido con unas 10 personas que se dedicaban a mantenimiento. Todas estas personas podían tocar la build.

El principal, con mayúsculas, problema con el que nos encontrábamos era la cantidad de commits que se hacían. El proyecto estaba en una fase fuerte de crecimiento así que había montones de funcionalidades que subir. Esto hacía que los commits fuesen constantes, y difíciles de controlar. Y como en toda época de rush, como no, las revisiones de código destacaban por su ausencia.

Total, que con tal cantidad de commits simultáneos, por muchos tests que hiciésemos (que se hacían) era muy habitual el romper la build. Pero ese no era el problema. El problema de verdad es que la gente seguía haciendo commits cuando la build estaba rota, lo cual presenta varios problemas:

  1. No sabes que tu código va a funcionar. Por mucho que esté funcionando en tu build local, al estar la build rota, no tienes la certeza de los cambios que ha subido otra gente, así que nunca sabes si esos cambios te pueden afectar.
  2. Si no se protege la build, os cambios se acumulan. Todos esos cambios, son cambios no probados en un entorno de integración. Cuanto más tiempo pase, más grande es el problema. Cuantos más commits se acepten con una build rota, más problemas potenciales están entrando en el código. El número de errores crece. El código se vuelve más inestable.
  3. A mayor número de cambios, más difícil es el recuperar la build. Si los cambios se van acumulando y acumulando, nos encontraremos que al corregir el primer error aparecen más errores. La única solución que queda es ir corrigiendo error tras error hasta que la build vuelva a funcionar. Cuanto más código incontrolado permitamos, más tiempo nos llevará arreglar la build.
  4. En el peor de los casos, no hay otra solución que volver atrás. En el peor de los casos nos encontraremos con que el código que se ha subido se cruza y no queda más remedio que revertir los cambios, con la consiguiente perdida de tiempo. Los equipos tendrán que pararse y ver por qué sus funcionalidades se han solapado.


Todo esto se ilustra en la captura de pantalla siguiente:



Entre 1 y 2 hay un montón de commits. Llega un momento en el que alguien se da cuenta de que se ha roto la build, y comienza el proceso de arreglar la build. En 2 se arregla algo, pero no es suficiente. En 3 algo más, pero sigue sin ser suficiente. En 4 finalmente se arregla, pero han sido necesarios 10 arreglillos para conseguirlo. Cuando si la build se hubiese arreglado en el momento de detectar el error no se hubiese perdido tanto tiempo.

¿Soluciones?

  • Involucración del equipo. La build debe de ser colectiva y todo el mundo tiene parte de responsabilidad en controlar que esté siempre sana. Muy a menudo la responsabilidad recae sobre el jefe de equipo, y si este falta se hace la vista gorda. Esto al final perjudica a todos. Si alguien ve que la build está rota, debe alertar de ello e investigar a ver qué está pasando.
  • No hacer commits si la build está rota. Tan simple como esto. Si la build se rompe, lo mejor es no hacer commits. No importa que el código sea muy urgente. Como desarrolladores, si hacemos commits, puede ser mucho peor para nosotros. Es mucho más efectivo el esperar a que la build esté estable y subir el código con la seguridad de que no vamos a romper nada. Además, así nadie nos meterá en el lio de arreglar la build después ;)
  • La técnica de la botella. Si las dos primeras no funcionan, la técnica de la botella es super-efectiva. Ya había escrito sobre eso aquí. Se compra una botella, que sea grande que hará falta. Cada vez que alguien rompe la build, se ponen 50 céntimos, un euro o algo así. Que no sean 10 céntimos porque entonces no duele demasiado :) Esto es mano de santo. En cuanto alguien ve que se va dejando un par de euros al día, pasa a ser mucho más cuidadoso con los cambios que hace. Además tras unos meses se puede hacer una cena a la salud de la build. La desventaja de este sistema es que no funciona demasiado bien con equipos deslocalizados :)
  • No permitir commits. Podríamos bloquear el repositorio de código fuente si la build se rompe. Esta es una solución bastante drástica que normalmente es perjudicial. Puede funcionar bien sólo cuando el equipo es pequeño. Si el equipo es grande y hay mucho código, esta medida tendrá el efecto de cuello de botella.
  • Revertir automáticamente el código que ha causado el error. Esta fue la medida que se aplicó en la empresa que os comentaba antes. La situación era tan complicada que no quedó más remedio que revertir de inmediato cualquier código que rompiese la build. Es un poco drástico pero dada la magnitud del problema, fue necesario. La gente comenzó a ser mucho más cuidadosa cuando veía que sus cambios se rechazaban una y otra vez.
  • Build en dos fases. En sistemas y equipos complejos. Otra alternativa es mantener dos builds. Una más inestable, en la que los desarrolladores van haciendo sus commits, y otra estable que nunca fallará. La primera sería una build permisiva, pero que como siempre, habría que respetar. La segunda aceptaría sólo código que ha pasado la primera build, y siempre estaría completamente estable. La idea es que si alguien necesita el código más reciente en cualquier momento, no tenga que esperar a que se arregle la build. Esto yo lo veo como un modelo complejo sólo apto para empresas grandes que tengan necesidades muy específicas.


En fin este tema daría para mucho hablar. Seguro que muchos estais familiarizados con el mismo y lo vivis en el día a día. Me encantaría leer vuestros comentarios y saber si tenéis este tipo de problemas y que hacéis vosotros para solucionarlos.