Documentation vivante : comment nous automatisons la création et la mise à jour de notre documentation

AntoineJ
YounitedTech
Published in
8 min readSep 17, 2020

En tant que développeur, nous partageons souvent le même constat au sujet de la documentation de notre produit :

  • L’information est difficile à trouver : éparpillée dans des Sharepoints, boites emails, wikis, fichiers Word, Powerpoint, etc.
  • L’information devient rapidement obsolète : le coût de maintenance est parfois élevé
  • Ce n’est pas intéressant d’écrire une documentation, ce n’est pas motivant de mettre à jour des diagrammes sur Visio ou Draw.io.

Les questions que l’on s’est posé : peut-on automatiser ces tâches de documentation ? Et/ou peut-on le rendre fun ?

Spoiler : la réponse est oui, c’est ce que l’on va voir dans cet article :)

Objectif : générer et mettre à jour des diagrammes avec de l’information “utile”

Notre contexte

Chez Younited Credit, nous proposons des crédits à la consommation mais pas à tout le monde, il existe pour cela des workflows d’éligibilité. Ces derniers sont complexes et varient en fonction de ce que nous appelons le “business context” (pays, produits, apporteur d’affaire, etc)

Notre premier cas d’utilisation est d’afficher tous ces workflows dans des diagrammes avec des descriptions.

Produits existants

Tout d’abord, regardons s’il existe des produits sur le marché. Peut-être pouvons-nous gagner un temps précieux avec un logiciel sur étagère.

  1. Commençons par nos IDE qui permettent souvent de générer des diagrammes.

Exemple avec un diagramme de classe dans Visual Studio :

Cela peut être utile dans certains cas mais cela ne correspond pas à notre besoin. Nous souhaitons afficher des diagrammes avec de l’information liée au métier et non décrire les détails de l’implémentation.

2. Il existe également des outils d’extraction de commentaires structurés comme Doxygen qui permettent de générer une application web.

Même problème, cela génère une documentation plutôt technique qui ne correspond pas à nos besoins.

3. Nous utilisons Azure Devops pour notre tooling build/git/release. SpecflowTeam propose une extension nommée SpecFlow+LivingDoc permettant de configurer des tests avec Specflow.

Cela permet de brancher à partir du repository Git les tests et exemples en Gherkin.

C’est déjà beaucoup mieux. Le Behavior Driven Developement (BDD) est une bonne pratique en conception logicielle. Malheureusement, cela ne correspond toujours pas à notre besoin.

Rapidement, on se rend compte qu’il n’y a pas de silver bullet, il va donc falloir coder. Cela tombe bien, un des objectifs est de rendre la création de la documentation fun.

Notre approche

La documentation “devient” du code : cela fait partie du système comme toute autre fonctionnalité.

Dans notre implémentation, nous avons défini 3 règles :

  • Tout documenter n’a pas de sens
  • Définir en amont les informations pertinentes à extraire
  • Il faut un vrai retour sur investissement sur chaque développement dédié à enrichir la documentation

Nous avons donc analysé les besoins et priorisé les résultats en fonction de 4 critères :

  • La complexité : nous ne souhaitons pas trop complexifier le système pour des besoins de documentation
  • Le coût du développement : doit-on réaliser un gros refactoring, combien de temps prendra le développement
  • Le temps de support : diffuser certaines informations en permanence à jour permettrait de dégager du temps à l’équipe en limitant au maximum certaines questions/demandes de support récurrentes
  • L’irritant : ce qui peut gêner les utilisateurs dans l’utilisation ou la compréhension du produit, tout ce qui a trait à leur satisfaction

5 Techniques

Nous avons défini 5 techniques qui permettent d’atteindre notre objectif, dont le but est d’aboutir à ce que l’on appelle le “code augmenté“.

1. Le DDD et le principe d’ubiquitous language

Le Domain Driven Design (DDD) est une approche de conception où les règles métier doivent être centrales. Le DDD implique de nombreux éléments mais c’est surtout la notion d’ubiquitous language qui nous intéresse ici. Cela signifie qu’il faut échanger avec le métier, discuter pour en extraire leur vocabulaire, leurs mots-clés, leur jargon. Cela doit se retrouver dans le nommage des éléments classes, méthodes, variables, etc.

Grâce à cela, les informations pourront être extraites directement, sans renommage et restructuration pour être comprises par les utilisateurs.

Cela nous permet ensuite, avec un simple Regex de transformer nos noms techniques en détectant les majuscules pour ajouter un espace : on passe donc d’un nommage du code (camelCase ou PascalCase) à un nommage compréhensible à l’affichage par l’utilisateur.

Une classe “métier“ :

On transforme le nom :

Pour au final afficher :

2. Les principes de Réflexion

La réflexion (ou introspection) est la capacité pour un programme à examiner sur ses propres structures. Ainsi le programme peut être analysé et manipulé pendant son exécution. Nous pouvons donc travailler sur des données dont nous n’avons la complète connaissance à la compilation mais seulement à l’exécution.

Voici un exemple de réflexion nous permettant de récupérer les informations de base sur nos workflows (son nom, la description, les différentes étapes, les paramètres des étapes, etc.)

3. L’utilisation des attributs

Les attributs nous permettent d’ajouter de l’information dans notre code afin de lui donner plus de sens. Ces informations peuvent ensuite être extraites par réflexion.

Exemple :

Il peut s’agir de texte afin d’illustrer des diagrammes (Description) ou de « meta-données » destinés à ajouter des règles métier pour la documentation vivante (DisplayOnDynamicWorkfowDocumentation).

Ce concept d’attribut est très important, on garde l’information au plus près du code pour que la documentation évolue avec le code. On a ici une technique concrète en réponse à la problématique de documentation rapidement obsolète.

Le code simple ci-dessous permet alors d’extraire la description d’un workflow :

4. L’utilisation systématique de structures de données

Concrètement, il est impossible d’extraire de l’information du code simplement s’il contient des structures if et switch. Il est donc nécessaire de créer des structures de données qui permettent ensuite à un algorithme d’appliquer des règles souhaitées.

Si le code contient des if/switch il est nécessaire d’effectuer un refactoring au préalable :

  • Repérer les structures de données utilisées
  • Vérifier la présence d’une bonne couverture de tests unitaires, et si ce n’est pas le cas la créer
  • Repérer les règles de gestion
  • Créer une structure de données avec un ou plusieurs objets complexes contenant l’ensemble des données utilisées dans l’algorithme
  • Créer un algorithme qui réalise le même résultat avec la nouvelle structure de données
  • Vérifier le fonctionnement ISO avec les tests unitaires

L’ensemble des données décrivant l’algorithme étant désormais dans une structure de données, ces informations peuvent être extraites par réflexion.

Un exemple réel de notre solution serait complexe à représenter ici, voici un exemple simplifié qui illustre notre méthodologie.

Un premier workflow

Un deuxième workflow

Ces 2 classes représentent 2 workflows basiques codés d’une telle façon que l’extraction des données est impossible. Il faut donc les refactorer.

Nous repérons le fonctionnement suivant :

  • Un workflow possède un nom lié à son contexte (dans notre cas France ou Espagne par exemple)
  • Un workflow possède une liste d’étapes. Chaque étape peu être en succès ou en échec et conditionner la réussite du workflow.
  • Une fois toutes les étapes réalisées, on doit pouvoir soit mettre à jour les données, soit les valider.

Le code refactoré est le suivant :

Quelques classes pour les structures de données

On crée les données exhaustives de la configuration des workflows

On crée ensuite un algorithme agnostique du contexte qui se charge uniquement d’appliquer les opérations en fonction des données de sa configuration

Grâce à cette méthodologie, nous pouvons extraire des informations de n’importe quelle portion de notre base de code. Evidemment sur du code legacy, le coût du refactoring peut-être élevé en fonction de l’état initial du code.

5. La génération de diagramme dynamique

Une fois les informations extraites du code nous avons ajouté une route avec un endpoint sur notre Api afin de pouvoir récupérer les données sérialisées en Json. Il faut ensuite les afficher : nous avons choisi de créer une application web Angular.

Pour générer automatiquement des diagrammes, nous avons choisi MermaidJs pour ses fonctionnalités avancées et ses diagrammes proposés qui correspondent à notre besoin.

Concrètement, il s’agit de transformer du Json en Markdown qui peut être interprété par MermaidJs.

Exemple basique :

Nous réalisons cette opération dans notre application web via des algorithmes en TypeScript.

Nous avons donc en 3 étapes :

1. Le code

2. Le Json

3. Le diagramme

Conclusion

Objectif : générer et mettre à jour des diagrammes avec de l’information “business” réussi !

  • Les informations essentielles liées à notre produit sont disponibles à un seul endroit, pas de perte de temps à chercher l’information.
  • Ces informations sont toujours à jour et évoluent systématiquement avec les nouveautés du produit.
  • Il n’y a pas de risque d’oubli dans la documentation des workflows car on extrait le code : même un nouveau développeur arrivant dans l’équipe, qui crééra un nouveau workflow génèrera une documentation associée sans erreur.
  • Les nouveaux workflows sont générés automatiquement et sans effort car ils s’agit seulement de respecter quelques conventions dans le code.
  • Le temps passé à créer et maintenir de la documentation “à la main” peut être réinvesti sur d’autres tâches.
  • Le temps passé à créer de la documentation reste agréable car il s’agit de code : ce n’est plus une contrainte.

Un exemple concret de l’application web :

Cet exemple a été notre premier cas d’utilisation. La méthodologie a été réutilisée sur d’autres projets pour afficher également du texte ou des tableaux de données, avec succès !

--

--