miércoles, noviembre 17, 2010

Always ship trunk

miércoles, noviembre 17, 2010 por Martín

Paul Hammond product manager de Flickr hizo una presentación en Velocity 2010 donde hablaba lo anticuados que están los sistemas de control de versiones cuando toca crear aplicaciones web.

Durante los últimos años parecía que SVN se había convertido en el rey de los sistemas de control de versiones, pero pronto aparecieron nuevos jugadores. Mercurial y Git son formas diferentes y más distribuidas de controlar el ciclo de desarrollo de software, pero según Paul, ninguno de todas estas alternativas está realmente pensada para el desarrollo web. Y lo cierto es que si lo pensamos fríamente y dejando a un lado las preferencias personales, no le falta razón.

La principal razón para crear una rama ha sido siempre la misma. Ese cliente que pide esa funcionalidad especial, que además la tenemos que hacer para ayer, y que vamos a dedicar a unas personas concretas a que la hagan mientras que el resto del equipo hace sigue con su desarrollo. Esas ramas pueden quedarse ahí o ir adquiriendo vida propia, e incluso evolucionar a productos nuevos, quien sabe. Pero el desarrollo en ramas, tal y como comenta Paul Hammond, parece estar más orientado a las aplicaciones tradicionales de servidor o de escritorio que a la web.

Paul argumenta que en la web no hay versiones, hay la versión. Esa es la versión que manejarán tus usuarios. Bueno, en realidad no es así, no es tan fácil. Tenemos entornos de producción, pre-producción, desarrollo, betas, QA, unos tendrán unas funcionalidades, otros tendrán otras funcionalidades. Incluso podemos querer probar ciertas funcionalidades en producción pero en modo oculto, o habilitarlas para un cierto subconjunto de usuarios, o tener la capacidad de habilitar o deshabilitar ciertas funcionalidades en tiempo real, o hacer tests A/B para comparar la efectividad de ciertos cambios, y un largo etcétera de posibilidades.

¿Existe algún sistema de control de versiones que te ayude a hacer esto? No, o al menos Paul no lo conoce (yo tampoco). La solución son añadir condiciones al código. Todo esto añade complejidad y puede ser bastante peligroso, pero por otra parte resulta muy efectivo. La recomendación general es guardar los switches en algún lugar centralizado donde se pueden habilitar o deshabilitar fácilmente.

A mi por ejemplo esta es una de las cosas que más me gusta de Grails, copiado de Rails y que te permite tener diferentes entornos de ejecución con diferentes configuraciones e incluso crearte tus propios entornos. Todo eso lo podemos combinar con algunos interruptores que nos permitan habilitar o deshabilitar funcionalidades en tiempo real y tendremos una única aplicación en la trunk que podremos controlar a nuestro antojo.

Sencillez operacional vs. complejidad en la configuración. ¿Qué preferís vosotros? ¿Tiene sentido el tener múltiples branches en el mundo web?

PS. Tenéis el enlace a la presentación arriba, pero hay más notas aquí.

comments

4 Respuestas a "Always ship trunk"
Peibol dijo...
21:36

Tiene sentido tener ramas, básicamente dividiendo estable de inestable, y finalmente todos los sabores de "en desarrollo" y "experimental".
No se que experiencia tendrás con git o con mercurial, pero el asunto es que SVN está pensado para hacer branches, y git/mercurial está pensado para hacer merges.
Esto hace que sea realmente fácil mantener varias ramas (dev, pre, pro, funcionalidadX, etc) en el mismo repositorio, sin ensuciar en ningún momento una con la otra, y cuando (pro ej.) se considera que dev es lo suficientemente estable para llevarlo a pre, se hace un merge y santo remedio.

En la empresa en la que trabajo hemos pasado de SVN a mercurial justamente porque estamos desarrollando web y estamos llevando como mínimo 2 ramas a la vez (dev y pre) y nos ha quitado muchos problemas de encima.

Otro asunto es que quieras hacer una aplicación muy configurable, lo cual en realidad se trata más de un asunto de arquitectura de la aplicación que de las ramas que utilices en el desarrollo.

Saludos


Martín dijo...
22:28

Muy interesante Peibol.

Me imagino que lo hacéis porque el equipo de desarrollo habrá avanzado en la funcionalidad y llega un momento en que alguien protesta y hay que realizar ajustes en pre/pro, y claro no se puede meter lo de dev.

No me meto en las formas de hacer o no hacer, aquí cada uno tiene su librillo. A mi personalmente me gusta que trunk=pre=prod. Evidentemente te fuerza a tener una trunk muy sana, respaldada por un buen sistema de integración continua y una buena build.

¿Cómo gestionar las funcionalidades experimentales? Yo soy partidario de desarrollarlas en ramas aparte que despues se mezclen con la trunk. Pero mi ley personal es que si mañana a las 14:25 te dicen quiero una build, siempre tiene que ser posible dar código totalmente estable.

Pero ya te digo esto cada uno tiene que jugar con las opciones y encontrar el equilibrio que le haga funcionar mejor. No creo que haya una única forma.


Dani dijo...
1:57

Una opinión que he visto algo extendida(y más con los git/mercurial) es crear una rama por funcionalidad en la que se está trabajando, precisamente para mantener el trunk estable.

Yo eso de tener ramas para dev, pre, pro o cualquier otro entorno no lo termino de ver claro. Pienso que es más fácil de mantener tener una configuración por entorno y hacer tags para cada versión que se despliegue. Pero vamos, que a cada uno trabaje como más cómodo le resulte :)


Peibol dijo...
21:45

Para mi lo interesante de tener separadas las ramas de dev/pre es la posibilidad de hacer refactorizaciones grandes sin perder la posibilidad de enviar a producción una versión a pre/pro (para mi pre y pro son lo mismo, solo que pro es pre validado por el cliente) en cualquier momento, cosa que con la configuración solamente no se puede hacer ya que se está modificando el código, más que la configuración.

De esta manera dejas pre/pro tranquilo mientras que en la rama de dev puedes hacer y deshacer a placer, rompiendo y saneando todo lo que quieras.
Suma TDD e integración continua y tienes la libertad de cambiar la aplicación desde los cimientos en cualquier momento, sin dejar de tener un pre estable.

Nosotros solemos tener varias ramas de desarrollo, que vienen a ser un DEV más experimental aún, y es donde se hacen los cambios "grandes" o los bloques de funcionamiento importantes.
Se hace así simplemente por tenerlos compartidos entre todos, así no se pierde código aunque se muera alguno de los discos de los equipos (puede pasar, y es lo que tiene la naturaleza descentralizada de HG) y cuando esa rama experimental está lo suficientemente avanzada, simplemente se la lleva a la rama de DEV y se cierra. Y posteriormente, DEV se lleva a PRE.

En lo que hemos ganado más con el paso a HG (mercurial) es en la potencia que tiene al hacer los merges entre ramas (en realidad entre nodos, las ramas solo son nombres), una tarea del todo manual en cvs/svn en HG es prácticamente automática.
Además que la herramienta mantiene la trazabilidad del origen de los merges en el repositorio, con lo cual es muy fácil de seguir y de corregir o modificar, así como hacer un rollback a cualquier punto. La principal diferencia es que SVN es lineal, un commit es padre de otro, en git/HG un commit puede ser padre de N commits, y un merge es siempre hijo de 2 commits previos.
Es un poco raro de explicar, sinceramente, si no has usado una herramienta como git/HG te diría que la pruebes porque el cambio merece la pena.

Saludos