Archive

Archive for July, 2007

Algunas ideas de cómo usar subversion

July 5th, 2007

Hace ya algunos años que comencé a usar SCM, primero fue CVS y ahora subversion. Existen otros muchos que algún día me gustaría probar, especialmente los distribuidos. Este tipo de herramientas se encargan de mejorar ciertas tareas que necesitamos realizar en distintos contextos. La finalidad de su uso puede ser variada. Personalmente uso subversion (svn) tanto para tener organizados mis script y archivos de configuración de los sistemas que uso, como para el desarrollo de proyectos software.

Dos de las ventajas que más destaco de la colaboración en proyectos de software libre es el intercambio de conocimiento y darse cuenta de que existen otras formas de hacer cosas que en muchos casos mejoran nuestras propias metodologías y resultados. Aunque subversion tiene un conjunto de operaciones cerradas, la forma de organizar nuestros repositorios es completamente abierta. Siempre que me surgía algún problema con los repositorios pensaba que algo no debía estar haciendo correctamente porque si proyectos de software libre en los que participan decenas de personas evolucionaban de forma fluida y constante, mis proyectos (que son mucho más pequeños) también debían hacerlo. Me resultaba difícil pensar que ellos también se tuvieran que enfrentar a los mismos problemas.

A continuación expongo algunas ideas que describen la forma en la que trabajo con los repositorios de subversion.

Definir nuestro repositorio con la siguiente estructura de directorios:

  • /trunk: Este directorio se caracterizará por ser uno de los directorios con mayor actividad. En él se almacenarán las últimas implementaciones. Parece lógico pensar que el estado del proyecto que contiene, es inestable. Sobre este directorio trabajarán aquellos desarrolladores que estén implementando nuevas funcionalidades y/o refactorizando algunas partes del proyecto.
  • /tags: En este directorio se almacenarán instantáneas del proyecto. Estas instantáneas relacionan el proyecto con un instante de tiempo. Al igual que sucede que las fotografías, estas instantáneas son necesarias para recordar ciertos hechos o sucesos. Algunos hechos que considero necesario recordar a lo largo de la vida de un proyecto software:
    • Las distintas versiones (release) que se van generando dependiendo de nuestra planificación (roadmap). Por ejemplo, /tags/1.0.0, /tags/2.1.0-beta o /tags/2.8.5
    • Presentaciones o demostraciones que se suelen realizar a directivos, clientes o usuarios finales que necesitan ver el proyecto en su último estado. Evidentemente ese último estado se ha concebido horas antes de la presentación y en raras ocasiones ha dado tiempo a realizar pruebas unitarias, y menos aun pruebas de sistemas o funcionales. Aunque veremos que esto también se puede mejorar con una arquitectura e infraestructura que nos permita modelar nuestra metodología y filosofía de trabajo en la que la integración continúa estará presente.
  • /branches: A diferencia de las etiquetas (tags), las ramas son instantáneas que evolucionan. Por lo tanto, en este directorio almacenaremos una instantánea que bien se ha podido obtener de la rama principal (trunk), de otra rama (branch) o de una etiqueta (tag). Algunas situaciones en las que considero necesario crear una rama:
    • Para almacenar las versiones que compartan la parte mayor de nuestro sistema de versionado. Por ejemplo, en el caso de estar usando un sistema de versionado compuesto por tres bloques (X.Y.Z), nos interesará crear una por cada par X.Y. De esta forma, dispondremos de una rama para mantener las versones de la forma X.Y. Supongamos que acabamos de obtener la primera versión de nuestro proyecto, y comenzamos a versionarlo por 0.1.0. Este justo instante deberemos generar la correspondiente etiqueta 0.1.0 a partir de la rama principal (trunk). A continuación generaremos la rama 0.1 partiendo de la etiqueta 0.1.0. En nuestro roadmap del proyecto estarán descritas las nuevas funcionalidades que se irán implementando en la rama principal y que originarán la versiones de la forma 0.2.x. Sin embargo, es muy probable que nuestra primera versión (0.1.0) tenga problemas que debamos resolver. En ese caso los problemas serán resueltos sobre la rama 0.1 y originarán nuevas versiones de la forma 0.1.1, 0.1.2, 0.1.3, etc.. Cada cambio que se realice sobre las ramas creadas para este fin, deberá ser reflejado si procede sobre la rama principal. Puede darse el caso de que el problema ya haya sido resuelto en la rama principal.
    • Las ramas para las versiones de la forma X.Y se crean para el propio mantenimiento de estas versiones dado que es aquí donde se han incorporado nuevas funcionalidades y éstas son candidatas a generar problemas. Por eso siempre se ha dicho que las versiones terminadas en 0 son menos estables.
    • A lo largo de la vida de un proyecto es muy probable que tengamos migrar a versiones más recientes de las librerías o frameworks de los que nuestro proyecto puede depender. Estas migraciones suelen ser delicadas porque pueden conllevar a una refactorización en nuestro código (patrones, métodos obsoletos, interfaces nuevas, etc). Para que estas migraciones no afecten directamente al desarrollo de nuestro proyecto es aconsejable crear una rama partiendo de la rama principal en que parte de los recursos de nuestro proyecto evaluen el impacto de tal migración. Cuando la migración se ha realizado satisfactoriamente los cambios realizados deben pasar a la rama principal. Ésta pudiera ser una de esas ramas que, por el motivo que las originó, no continúen evolucionado.
    • En algunos casos nos puede interesar que cada programador disponga de una rama propia de la forma user-dev para que puedan realizar sus pruebas y que éstas no interfieran con el resto de tareas. Adicionalmente, es una forma muy sencilla de tener una copia de seguridad y que sean ellos mismos quienes decidan cuando hacer los commits. Por regla general, suelo hacer commits asociados a una tarea (un commit, una tarea).

Si nuestro proyecto está formado por módulos perfectamente diferenciados quizás nos interese crear un nivel previo a la estructura antes descrita. Por ejemplo, podemos crear client-app/ y server-app/, y debajo de estos directorios crear nuestros directorios trunk, branches y tags.

Categories: Herramientas Tags: