Industrialisation des développements : automatisez votre base de données

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 »).

Principes directeurs

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 :

  • La base de données évolue en même temps que le code ;
  • Il faut donc tester en continu la base de données pour permettre un refactoring sans conséquence, comme on le fait avec le code source ;
  • Il faut outiller les processus autour de la base de données afin d’améliorer la productivité des développements et leur industrialisation.

Les outils existants reposent sur les principes suivants :

  • Un schéma doit pouvoir être détruit et recréé de manière répétable ;
  • La version du schéma doit être identifiable ;
  • La montée et la descente de version doivent être automatisées ;
  • Les changements appliqués doivent être connus ;
  • Un changement doit pouvoir être défait ou annulé ;
  • Un changement précédemment appliqué ne doit pas être modifié mais un nouveau changement doit être créé.

Principes techniques

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 :

  • développement d’une nouvelle fonctionnalité : il est ainsi possible de créer un script et de l’exécuter plusieurs fois (montée de version, test, modification, descente, puis nouvelle montée de version). La descente de version permet ainsi de faire revenir la base de données dans l’état précédent ;
  • Ré-alignement automatique du schéma avec le code quand la version de la base de données n’est plus la bonne. Ce cas intervient quand il faut corriger un bug sur la version de production ou au passage à une autre branche de développement, ou encore quand un script a été exécuté puis modifié.

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.

Bonnes pratiques

Les bonnes pratiques poussées par ces outils sont :

  • Scripts (SQL ou XML pour Liquibase) stockés avec le code source
  • Une base de données par développeur (réaliste quand la gestion de la DB est automatisée, hors problème de coût de licence) ;
  • Une base de données commune à l’équipe qui représente l’état complet et stable ;
  • L’intégration continue déroule l’ensemble des scripts à chaque livraison ;
  • Un script qui a déjà pu être exécuté ne doit plus être modifié. On risque sinon de désynchroniser les scripts et le schéma  La livraison d’un nouveau script est nécessaire dans ce cas. Ce script est un refactoring du précédent. La seule exception est un script buggé qui provoque la perte de la donnée. Il ne faut donc pas que ce script atteigne les autres environnements.

Les outils existants

Liquibase : puissant mais complexe

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 :

  • d’être compatible avec plusieurs moteurs SQL ;
  • de donner une sémantique aux opérations (on écrira un <renameColumn> plutôt qu’un alter table) ;
  • de générer automatique des instructions de rollback (par exemple, un <createColumn> sera compensé par un <dropColumn>).

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>

Les pragmatiques

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;

Conclusion

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 :

  • Les outils de migration de bases de données nous permettent de gagner en efficacité lors de la manipulation du schéma de la base de données ;
  • Ces outils fiabilisent les traitements en les automatisant et en les intégrants à l’usine de développement ;
  • Ces outils apportent de bonnes pratiques permettant un travail en équipe plus efficace ;
  • Ces outils sont disponibles, simples à mettre en place et OpenSource.

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é.

4 commentaires sur “Industrialisation des développements : automatisez votre base de données”

  • Content de voir (enfin) un article sur cette "grand oubliée". J'aime beaucoup le chapitre sur les bonnes pratiques. Autre chose : toujours laisser à dispo dans un répertoire commun un backup de la BDD. Afin que si un développeur crashe sa base il a un backup à dispo. Ou si un nouveau arrive il peut tout de suite commencer avec une version à jour pour le développement de la DB Personnellement, j'ai mis en place un process basé sur - un backup de départ qui est la BD de référence - une série de scripts sql - un gros script pour lire le sql et mettre à jour la BDD de référence et créer un backup de référence pour le développement La question de l'ordre d'application des scripts sql est importante. Notamment quand on n'utilise pas d'outil
  • L'automatisation est critique effectivement, mais il ne faut pas oublier le versioning de la base de données. L'ensemble des outils cités prennent en charge plus ou moins bien l'automatisation du déploiement, mais n'adressent pas la génération des scripts (SQL ou XML) initiaux. Ni d'ailleurs la gestion du merge entre 2 branches de développement parallèle. Liquibase est très puissant, mais l'écriture de tels scripts est très consommatrice en temps. C'est pour adresser l'industrialisation dès la phase de conception / développement que nous avons mis en place neXtep designer : un produit gratuit sous licence GPL qui propose le versioning de vos bases de données. Il s'agit d'un environnement de développement dans lequel votre structure (et bientôt vos données) sont sous controle de version : vous travaillez directement sur le modèle, l'outil se charge de générer les scripts de delta automatiquement. L'IDE est basé sur eclipse et propose des diagramme de modèlisation CASE, la gestion des dépendances, un puissant éditeur SQL, la synchronisation directe ou reverse, la génération de SQL à partir de n'importe quel delta de version, etc. Nous songeons à travailler avec le projet liquibase pour proposer des générateurs de changeset XML dans une future version. Nous sommes en discussion avec Nathan sur ce point. Bref, pour en savoir plus : http://www.nextep-softwares.fr La présentation des concepts est plus détaillée sur le wiki : http://www.nextep-softwares.com/wiki
  • Pour ma part j'utilise doctrine migrations ( http://www.doctrine-project.org/projects/migrations ) qui permet de versionner sa BDD et de faire des updates assez simplement et rapidement. C'est intéressant de parler de cette partie d'un projet car bien souvent elle est oubliée dès le début ce qui peut poser quelques problèmes par la suite quand les besoins évoluent.
  • C'est bien de parler de versioning BDD mais il faut préciser la manière de traiter les données contenues dans les structures. Qu'en est il ? Je n'ai pas l'impression que la gestion des données est particulièrement gérée. si ce n'est pas le cas, le versioning se limite finalement à la création d'un schéma "from scrath" accompagné d'un versioning d'interface.
    1. Laisser un commentaire

      Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha