Importer : mon projet de transformation de donnée

Transformations

Dans mon poste précédent, j’ai supervisé les migrations de données des nouveaux clients nous ayant rejoint et ayant besoin de retrouver les fiches déjà saisies dans leur ancienne application.

Historiquement, cette étape était laissée à la charge du client : des documents modèles étaient fournis, et l’équipe du client se chargeait de nous les retourner en temps et en heure avant la mise en production.

Cela présente plusieurs avantages:

  1. les données sont sous la responsabilité du client
  2. le format retenu (une feuille de calcul) ne nécessite pas de compétence ou d’outil particulier de la part du client et peut-être réalisé sans risque.

Sauf qu’avec le temps, la complexité des reprises de données a explosé: au lieu d’avoir un fichier seul contenant les données à charger, le nombre de fichiers s’est multiplié, chaque feuille de calcul se rapprochant de plus en plus d’une table au sein d’une base de données.

Il ne s’agissait plus seulement de s’assurer de la qualité des données fournies par le client, mais de:

  • Comprendre et reconstituer son modèle relationnel de données
  • Transformer chaque modèle pour l’ajuster à notre application
  • Générer les fichiers à importer.

Au lieu de demander au client de remplir les fiches lui-même, nous avons commencé à lui demander une extraction de sa base de données, pour faire ces opérations nous-même. Et c’est comme ça que j’ai commencé à développer ma propre application pour réaliser ces traitements.

L’idée centrale

Chaque feuille de calcul peut être assimilée à une table au sein d’une base de données. L’application va donc:

  1. charger un fichier principal,
  2. charger plusieurs fichiers de référence,
  3. effectuer des jointures entre eux,
  4. appliquer des transformations,
  5. produire un CSV final prêt à être importé dans une autre application.

Par exemple:

Au lieu d’écrire un script python (par exemple) pour chaque projet, j’ai choisi d’écrire une application capable de traiter les différentes configurations possibles. L’investissement est beaucoup plus élevé (mais j’ai pris plaisir à écrire le code), mais cela a payé quand j’ai été confronté à des reprises de plusieurs dizaines de milliers d’enregistrements, mettant en relations une dizaine de référentiels différents.

La solution

Aujourd’hui, le projet implémente un véritable DSL destiné à décrire comment agréger les données:

un fichier de règle décrit dans une première partie la manière dont les tables sont mises en relations les unes avec les autres, puis la présentation du résultat final.

# Génère un fichier csv ne contenant que trois colonnes
# et contenant les colonnes A, C et D du fichier source.
[sheet]
  columns = [
    ":A",
    ":C",
    ":D",
  ]

Les traitements sont exécutés pour chaque ligne du fichier source (sauf si des filtres sont appliqués), et le langage prend en charge:

  • Des opérateurs (concaténation, comparaisons…)
  • Des fonctions (texte, date)
  • Des fonctions d’agrégat (compteur, somme)

Mon bilan

Ce qui a commencé par un petit défi technique (est-ce que je peux lire un fichier XLSX en OCaml) s’est transformé au fil du temps. Je n’ai pas vraiment donné de nom à mon application, puisque j’en parle comme un «outil», mais je sens aujourd’hui qu’il a atteint un seuil de maturité, autant dans l’usage que je peux en avoir que dans le code. C’était la première fois que j’écrivais une application réalisant un traitement en abyme: ce n’est pas l’exécution du programme qui produit le résultat, c’est l’interprétation des règles données à l’application qui génère le fichier final.

Par moment, cela m’a donné ce sentiment vertigineux de faire quelque chose de plus grand que moi: les règles de transformation à appliquer étant tellement complexes qu’il ne m’est plus possible de les vérifier facilement, et de me rendre compte que je faisais confiance en mon application pour garantir le résultat attendu.

L’application est aujourd’hui utilisée par les collègues qui ont repris le poste que j’occupais et l’application répond au besoin qui l’a vue naître. J’ai en tête l’idée de préparer une interface graphique, mais qui ne révolutionnera pas son périmètre. D’une certaine manière, il est temps aussi de la laisser vivre sa vie sans moi.

Plus de détails ici (avec le code source) : https://git.chimrod.com/importer.git/about/