La semana pasada hablando sobre Visual Studio y como incluye una base de datos local sin instalar componentes adicionales, si te lo perdiste échale un vistazo aquí, mencioné que tener una base de datos por cada desarrollador, puede resultar mucho más productivo que utilizar una base de datos compartida por todo el equipo.

El modelo tracional: Una base de datos compartida

Habitualmente, un equipo de desarrollo comparte su base de datos, generalmente en un servidor dedicado a mantener las bases de datos de desarrollo.

Es evidente la primera implicación de este modelo, si todos los equipos de desarrollo mantienen sus base de datos ahí, este servidor requiere el mismo mantenimiento que uno de producción, dado que cualquier mínima pérdida de rendimiento o disponibilidad afectará a la productividad de todos

En realida esté es el menor de los problemas, existe otro que tiene mucho más impacto y que sólo sale a la luz si se trabaja suficiente tiempo en equipo siguiendo este modelo de bases de datos compartidas.

El problema

Supongamos que un desarrollador del equipo esta trabajando en añadir encriptación al almacén de contraseñas de la aplicación.

Mientras otro desarrollador del equipo, continúa trabajando con otras historias de usuario.

Por supuesto, nuestro equipo de ejemplo utiliza un control de versiones para su código. Finalmente nuestro primer desarrollador modifica las contraseñas en la base de datos, sin embargo, como resultado de ejecutar las pruebas funcionales descubre un bug en la funcionalidad y no está listo para subirlo al control de versiones.

Una base de datos compartida

Veis el problema? Sí, en el momento en que nuestro primer desarrollador ha realizado ese cambio en la base de datos, inmediatamente los test de autenticación del resto del equipo dejarán de funcionar. Es más, nuestro segundo desarrollador ni siquiera podrá iniciar la aplicación en caso necesario!

Esto que parece obvio, ocurre en más de un equipo, donde en ese momento todos dejan de trabajar en lo que estaban y comienzan a buscar al responsable que ha cambiado la base de datos.

Una base de datos por desarrollador

Hace tiempo que, cansado de estas interrupciones y pérdidas de productividad, decidí buscarle solución a este problema.

Si estamos creando código de manera local, pensé, y no subimos los cambios al repositorio principal sin haberlos validado antes, porqué no podemos hacer lo mismo con la base de datos?

Es decir, cada desarrollador de nuestro equipo tiene entonces una base de datos completa en su máquina, y mientras desarrolla puede hacer las modificaciones que quiera, sabiendo que no afectan a los demás miembros de equipo.

Reto: Compartir los cambios

Sin embargo, nos encontramos con un nuevo reto, y es que en el momento que subimos los cambios al repositorio principal, necesitamos compartirlos con el resto del equipo.

Lógicamente, hacerlo de forma manual, sería una nueva pérdida de productividad, incluso, dependiendo de la funcionalidad una pérdida total de tiempo.

Migraciones

De la misma forma que todos nuestros cambios de código están versionados, y nadie más los ve, hasta que están listos para ser compartidos, no podemos hacer lo mismo con la base de datos?

Podemos escribir el código DML necesario e incluirlo junto a nuestro changeset para que en cuanto el resto del equipo se baje el código, apliquen los cambios necesarios a la base de datos.

Es decir esto introduce una nueva tarea en nuestro flujo de desarrollo:

Una base de datos por cada desarrolador

Y ahora sí, cada cambio se encuentra asociado a su correspondiente en la base de datos. Hemos versionado nuestra base de datos, de la misma forma que versionamos el código.

Migraciones basadas en código

Yo programo en el lenguaje X# porque tengo que hacer migraciones en SQL?

La verdad es que este es el primero reto al asumir este modelo. De hecho, además de tener que escribir complejas instrucciones DML para migrar la base de datos, puede resultar complicado controlar la transaccionalidad de los cambios. No queremos que nuestra migración deje la base de datos de los demás en un estado irreversible!

Por suerte, tenemos frameworks disponibles que nos permiten escribir nuestras migraciones sólo con código, sin escribir prácticamente una línea de SQL.

En el caso de .NET tenemos dos, EF Migrations, compatible con los proveedores de base de datos que soporta Entity Framework, y FluentMigrator, proyecto en el que colaboré hasta su versión 1.0, con soporte pata múltiples bases de datos.

En resumen

  • Versiona tu base de datos, como versionas tu código
  • Por cada cambio que hagas a la base de datos, escribe su migración correspondiente
  • Apoyáte en frameworks que te hagan sencillo escribir las migraciones y controlar la forma en que se aplican

Termino con una pregunta, ¿cuál es otra ventaja de las migraciones, que ocurre como consecuencia de aplicar el modelo anterior?

Hasta la próxima semana!