Le grand oubli dans l'industrialisation des développements est la base de données, cette chose monolithique et statique qui n'évolue pas aussi vite et aussi aisément que le code. Au même titre que l'intégration continue et les systèmes de gestion de version pour le code source, il existe des outils permettant de fluidifier et d'automatiser le travail autour du schéma physique des données. Travailler avec ces outils permet de compléter une démarche Agile en permettant une réactivité forte face aux changements.
Une première partie de cet article concernera les principes et pratiques autour de ces outils (partie « boss compliant »). La deuxième est orientée technique (partie « geek aware »).
Dans son article paru en 2003 intitulé « Evolutionary Database Design », Martin Fowler pose les principes du design évolutif de base de données. Les points clés en sont :
Les outils existants reposent sur les principes suivants :
Sur le plan technique, le fonctionnement des outils de migration est simple. Ils se basent sur une table contenant la version de la base de données. La liste des scripts exécutés est conservée ainsi qu’une empreinte de chaque script afin de détecter une altération d’un script déjà exécuté.
A chaque lancement, l’outil de migration compare la version de la base et les scripts existants et propose la mise à jour le cas échéant.
Il est également possible de « descendre de version » le schéma (fonctionnalité disponible dans quasiment tous les outils). Il s’agit de remettre la base de données dans un état cohérent. Deux cas d’usage :
Même si la descente de version est utile, elle a néanmoins deux inconvénients. Le premier est que les instructions de descente doivent être écrites à la main. Les outils les plus simples fonctionnent sur le principe où chaque script contient une partie montée de version et une partie descente (voir l’exemple plus bas avec MyBatis). Seul Liquibase est capable de générer les instructions de descente de version grâce à son DSL.
Le deuxième inconvénient est que certaines montées de version ne sont pas réversibles (suppression de table ou de données). Dans ce cas, la descente ne sera possible que jusqu'à la version incluant ce type de modification. L'alternative est de recréer le schéma de zéro, une fonctionnalité que tous les outils proposent et qui est en fin de compte très rapide.
Les bonnes pratiques poussées par ces outils sont :
Liquibase est le plus connu des outils de migration de base de données. Il se base sur les patterns décrits dans le livre « Refactoring database ». À ce titre, il est conçu autour d’une approche théorique par pattern de refactoring.
Le noyau de Liquibase est son DSL basé sur XML qui a les avantages :
Liquibase est complet. Il s’intègre à Maven, Grails, Spring et Hibernate et supporte la génération de documentation ou encore la création d’un diff entre schémas.
L’inconvénient principal de Liquibase est une certaine complexité qui ne se retrouve pas dans les autres outils (XML, notion de changelog et de changeset, versionning sur id/auteur/chemin). La courbe d'apprentissage est donc plus élevée que les autres outils se basant purement sur du SQL.
Exemple de changeSet Liquibase :
<changeSet id="1" author="bob">
<createTable tableName="department">
<column name="id" type="int">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(50)"/>
</createTable>
</changeSet>
D’autres outils ne vont pas aussi loin que Liquibase en termes de fonctionnalités et d'abstraction mais leur approche est pragmatique et plus simple. Ils visent avant tout à automatiser la gestion des scripts SQL. Les principaux sont MyBatis Schema Migration, DbMaintain et C5 DB Migration.
Le principe de ces outils est assez simple et consiste à lancer une série de scripts stockés dans une arborescence répartie en version. Les actions sont tracées ce qui permet de connaître l’état du schéma.
Exemple d’arborescence organisée pour DbMaintain :
scripts/01_v1.0/01_products_and_orders.sql 02_users.sql 02_v1.1/01_add_barcode_column.sql 02_drop_itemcode_column.sql
Le schéma de base de données est mis à jour en exécutant :
dbmaintain.sh update chemin/vers/les/scripts
Dans le cas de MyBatis, les instructions de montée et de descente de version sont écrites dans le même script SQL. Exemple :
--// create product table CREATE TABLE PRODUCT (ID INT, NAME VARCHAR(255));
--//@UNDO DROP TABLE PRODUCT;
Les outils de migration de base de données permettent une meilleure productivité en levant certaines barrières au changement du schéma des données et ils rendent l'industrialisation accessible.
Les points clés à retenir sont :
Par extension, on peut imaginer qu'une application puisse se mettre à jour d'elle-même. En effet, il s’agirait de permettre à l’application de lancer les migrations de schémas quand elle démarre. Cette fonctionnalité réduit le temps de mise en production en supprimant l’étape de passage des scripts par les DBA. Liquibase propose déjà cette fonctionnalité.