Moi je code m’ADOC

Parlons documentation

En tant que développeurs, nous sommes amenés à produire du code évidemment mais également de la documentation : fichiers README, spécifications techniques/fonctionnelles, guide d’installation, manuel utilisateur, wiki, …​ N’oublions pas nos amis étudiants et le fameux rapport de stage.

Le but de cet article est de montrer comment mieux écrire sa « doc » en choisissant les bons outils collaboratifs provenant du monde Open Source. Préférons des outils simples, ouverts, gratuits, maintenus à jour par la communauté.

Attention au grand écart entre le monde du développement et les outils de la sacro-sainte documentation! À ma gauche, un univers industrialisé (IDE, GIT, releases) et à ma droite une suite bureautique (MsOffice, OpenOffice, …​) complétée d’un modeleur UML et d’outils annexes. À moins d’utiliser une GED ou des outils collaboratifs genre « GoogleDoc », la documentation est souvent stockée sur un répertoire réseau d’entreprise avec la fameuse technique du « copier-coller-suffixer »! MonFicher-v1.doc deviendra MonFicher-v2.doc et un dossier « archives » sera créé pour historiser les anciennes versions. Drôles de versioning.

La figure 1 illustre ce grand écart « Doc vs Code » pour une application, chaque branche ayant son propre cycle de vie. Et pourtant, lors d’une livraison, on se doit de réconcilier l’artéfact applicatif (WAR, ZIP) et l’artéfact documentaire (DOC, ZIP). À noter également que le code contient sa propre documentation interne (commentaire, JavaDoc). Nous y reviendrons un peu plus tard.

1-Doc vs Code

Figure 1. Doc vs Code ?

Et si la « doc » était du code? La figure 2 prend cette hypothèse. Et maintenant tout devient plus simple. Il faut néanmoins changer certains outils. En allant plus loin, tout code est documentation, dixit le dicton du développeur « la vérité est dans le code »!

2- Doc=code

Figure 2. Et si Doc = Code ?

Vive le fichier plat!

Le principe du MDA (Model Driven Architecture) a longtemps été mis en avant pour son côté rigoureux. Un modèle UML source contient la conception UML complète de l’application ainsi que sa documentation. L’application est ainsi générée à partir de ce « gros » modèle source. Cette approche, a priori séduisante, se confronte vite au problème du travail collaboratif et au versioning/branching/merging quasiment impossible. Ce frein limite le refactoring du code et de la documentation.

Le choix de MsOffice pour la documentation signifie des fichiers binaires, au mieux XML, ne permettant que difficilement le travail collaboratif, à moins d’investir dans les outils Microsoft adéquats : SharePoint, Office365, …​

Rien de mieux qu’un bon fichier plat. En effet, il est éditable par n’importe quel éditeur de texte. On peut l’intégrer sous sGit pour obtenir gratuitement le versioning et le merging. Notre code Java, JavaScript, …​ est contenu dans des fichiers plats. Pourquoi ce concept, admis pour le code, ne le serait-il pas pour la documentation? Par exemple, chez SQLI ISC (Innovative Service Center) France, nous repensons complètement notre SI et nos outils, dans le but d’améliorer la qualité de nos services et nos livrables. L’approche « As Code » prend un rôle central, au travers l’Infrastructure As Code entre autre. Tout doit être scriptable afin de garantir une reproductibilité. Notre SI se décrit ainsi par un ensemble de fichiers plats. Notre documentation, en asciidoc, rentre également dans cette philosophie via la « Documentation As Code ».

Asciidoc(tor)

Le bon outil pour écrire de la doc serait bien l’asciidoc. Il s’agit d’un language de balisage léger, créé en 2002. À partir d’un fichier texte source (ADOC), on peut générer des documents publiables (HTML, PDF, …​).

3- docs publiables

Figure 3. Une source, plusieurs documents publiables

Le processeur initial était écrit en Python. « Le contenu avant la forme », voici la devise d’asciidoc. Regardons ci-dessous un premier exemple de document avec son rendu HTML.

Table 1. Premier asciidoc

= Vite un exemple en Asciidoc

Mehdi Rebiai <mrebiai@sqli.com>

Introduction à http://asciidoc.org[AsciiDoc].

== Partie 1

* Point1

* Point2

** Point2.1

== Partie 2

. Item1

. Item2

4- exemple Ascidoc

La syntaxe asciidoc qui a eu du mal à percer au début, contrairement à son rival Markdown, semble bien ratrapper son retard depuis l’arrivée d’asciidoctor (http://asciidoctor.org).

Il s’agit d’un nouvel écosystème, basé sur la syntaxe asciidoc. Ce projet Open Source, dirigé par Dan Allen son « project Lead », a remplacé l’ancien processeur Python par une implémentation Ruby. De nombreux outils et intégrations sont proposés afin de simplifier l’écriture et la publication de documentation. Afin de prouver le succès grantissant de l’asciidoc, ce format est désormais géré par de nombreux acteurs du web dont GitHub et GitLab. Pour information, la documentation du célèbre SpringFramework a été écrit en asciidoc.

Continuons le parcours de nombreuses possibilités offertes par la syntaxe asciidoc, illustrées par l’outillage asciidoctor. La figure ci-dessous montre le mecanisme d’inclusion d’image, de vidéo, de code et d’autres fichiers asciidoc :

= Include

image::monImage.png[height=100]

video::monVideo.avi[]

 

[source,javascript]

—-

include::HelloWorld.js[lines=2..4]

—-

:val: cas1

include::test.adoc[]

:val: cas2

include::test.adoc[]

Personne n’imagine écrire une classe Java et milliers de lignes. De la même façon, n’écrivez plus de gros documents. Découpez-les et utilisez les inclusions. Autre point très intéressant, lorsque l’on souhaite inclure du code dans de la documentation, fini le « copier-coller » ou le « screenshot » qui provoque obligatoirement une décorrélation dans le temps. Utilisez l’inclusion de fichier code, en profitant même de la coloration syntaxe (via les outils coderay, pygments, highlightjs). L’inclusion peut être totale ou partielle, en précisant les lignes à extraire ou via des tags commentaire dans le source. On peut également définir un sommaire automatique, créer des variables et les utiliser, créer des tableaux (inclusion CSV possible), inclure des diagrammes (voir chapitre PlantUML), créer des formules mathématiques et plus encore.

Le principe du « Doc As Code » nécessite une phase de compilation de la documentation. Et oui, on compile sa doc, tout comme son code. La commande ci-dessous, propose la compilation d’un fichier monfichier.adoc et la création d’un fichier monfichier.html (HTML5 par défaut).

asciidoctor monfichier.adoc

La commande peut être complétée de paramètres (non exhaustifs) afin de « customiser » la compilation :

asciidoctor -D <output> -T <template> -r <requirements> monfichier.adoc

Il faudra préalablement avoir installé Ruby et la gem asciidoctor. Mais évitez-vous cette étape en utilisant Docker. Ce logiciel libre au succès grandissant est en passe de devenir un incontournable du monde informatique.

Asciidoctor propose une image officielle Docker. Le développeur peut ainsi déléguer la compilation de sa documentation à un conteneur « boîte à outils ». La commande vue ci-dessus est à positionner au niveau de <CMD> :

docker run –rm -v <WORKSPACE>:/documents/ asciidoctor/docker-asciidoctor <CMD>

Pour plus d’informations sur la syntaxe asciidoc ou sur l’outillage asciidoctor, n’hésitez pas à consulter le site http://asciidoctor.org, réalisé évidemment en asciidoc. Cette syntaxe asciidoc peut faire peur au début mais elle s’apprend très rapidement. Les mots clés à retenir sont Simplicité & Productivité.

Maintenant demandons-nous comment réaliser des schémas, des diagrammes avec cette approche fichier plat.

PlantUML

Pourquoi PlantUML (http://fr.plantuml.com) ? Tout simplement car c’est LA solution pour faire de l’UML à partir de fichiers plats. Cette solution Open Source s’intègre parfaitement avec l’outillage asciidoctor. On écrit des fichiers puml et on génère en sortie des images png, svg, …​ À notre le besoin d’installer l’outil graphviz (http://www.graphviz.org) pour le rendu de certains diagrammes.

Le fichier puml commence par @startuml et se termine par @enduml. La suite repose sur le principe de l' »ascii-art » pour dessiner les relations UML. De nouveau, on se focalise plus sur le contenu que sur la forme. On peut tout de même jouer sur le style et positionnement des formes.

Table 2. Premier exemple PlantUML
@startuml

interface Conference

Conference *- Talk

BdxIO .> Conference

@enduml

4- plantUMH

Tout comme pour asciidoc, avec PlantUML il y a une phase compilation. Cette dernière peut être exécutée de façon isolée via l’utilisation du jar plantuml.jar.

Génération de monfichier.png

java -jar plantuml.jar monfichier.puml

Mais on préfèrera la solution offerte par asciidoctor. Il suffit d’inclure le PlantUML dans un fichier adoc. On notera l’activation de la dépendance asciidoctor-diagram :

Génération de monfichier.html contenant le png du diagramme

asciidoctor -r asciidoctor-diagram monfichier.adoc

Mais de nouveau, l’image Docker officielle d’asciidoctor propose tout le nécessaire.

docker run –rm -v <WORKSPACE>:/documents/ asciidoctor/docker-asciidoctor <CMD>

Afin d’illustrer les possibilités de PlantUML, prenons un cas concret d’une application Web. Cette application réalise du « live rendering » de texte asciidoc et en PlantUML :

5- live rendering

Par où débuter lorsque l’on réalise un conception technique? Et bien cela commence souvent par la création de diagrammes de cas d’utilisation :

@startuml

:Utilisateur: –> (Evaluer ADOC)

:Utilisateur: –> (Evaluer PUML)

@enduml

6-utilisateur évalue

plantuml::puml/Usecase.puml[nom-fichier-image, format= »png », align= »center »]

Continuons par la réalisation du modèle de données et de l’API de services :

@startuml

class MyDoc {

– String code

– String result

}

interface Processor {

+MyDoc process(MyDoc myDoc)}

interface AdocService -up-> Processor

interface PumlService -up-> Processor

@enduml

7- l’API de services

Ensuite le diagramme de composants permet une bonne visualisation globale d’une application :

@startuml

node « Frontend » <<Module>> {

[/adoc] <<Route>> as route_adoc #Gold

[AdocController] <<Controller>> as contr_adoc #orange

[adoc.html] <<Template>> as templ_adoc #LightGreen

 

route_adoc ..> contr_adoc : define

route_adoc ..> templ_adoc : define

}

 

node « Backend » {

[AdocEndPoint] – AdocRest

}

contr_adoc .up.> AdocRest : consume

@enduml

8- diagramme de composants

Le classique diagramme de séquence n’est pas oublié. Vous noterez l’extrême simplicité de sa réalisation :

Table 3. Sequency

@startuml

actor Utilisateur

participant Frontend

participant Backend

 

Utilisateur -> Frontend : saisir adoc

activate Frontend

Frontend -> Backend : processAdoc

activate Backend

Backend -> Backend : doWork

Backend –> Frontend : get html

deactivate Backend

Frontend –>Utilisateur : rendu IHM

deactivate Frontend

 

hide footbox

@enduml

9-diagramme de séquence

Pourquoi investir financièrement dans des gros modeleurs UML alors qu’on les sous-exploite bien souvent. De plus, un modèle UML est rarement maintenu à cause de la lourdeur de la mise à jour. Le fichier plat et PlantUML semble bien répondre au problème. Ce type d’outillage n’ira jamais aussi loin qu’un véritable modeleur UML. Mais la force de PlantUML n’est pas là. En plus d’être gratuit, il rend facile le travail collaboratif et le refactoring. N’hésitez pas à vous référer à la documentation de PlantUML (http://fr.plantuml.com) pour plus d’informations.

Workflow de génération

Remplacer MsOffice et un modeleur UML par asciidoc et PlantUML ne fonctionnera que si le processus de génération est simplifié. En effet sans automatisation du « workflow de génération », ces outils resteraient confidentiels et réservés aux plus technophiles d’entre nous. Pour le poste du développeur, de nombreux outils proposent du « live rendering »: plugins dans IDE (Eclipse, IntelliJ), éditeur (atom.io), extensions navigateur (Chrome, Firefox), …​

Dans le cas classique d’un projet Java, la génération de la documentation peut s’intéger au cycle de vie Maven/Gradle, grâce à l’outil JRuby qui concilie Java et Ruby. À partir d’un répertoire src/main/asciidoc, un dossier target/generated-docs sera créé. Désormais, la compilation d’un projet impacte à la fois le code source et la documentation. Vous trouverez de très bons exemples Maven/Gradle sous GitHub :

Les développeurs JavaScript ne sont pas oubliés. Le projet asciidoctor.js propose un portage d’asciidoctor en JS, grâce à l’outil Opal. Des plugins Grunt/Gulp permettent ainsi de réaliser le même type d’intégration que Maven/Gradle.

Poussons la logique un peu plus loin: et si l’on écrivait un wiki en asciidoc, avec la contrainte d’avoir les fichiers des pages sous Git? Comment dynamiser la génération? Où stocker les pages HTML générées? Comment maîtriser les droits d’accès à ce wiki? L’outillage asciidoctor propose un plugin poussant les fichiers HTML générés vers le portail Confluence d’Atlassian. Mais n’y a-t-il pas une solution plus simple et surtout gratuite et basée que sur des outils Open Source? Que de questions, mais rassurez-vous, des outils existent! Le projet Hubpress permet de réaliser rapidement des blogs sous Github à partir de source asciidoc. Malheureusement cela ne pourra pas convenir pour les entreprises à cause du côté publique. L’outil awestruct permet la génération d’un site web statique. Il est développé en Ruby et propose un plugin asciidoctor permettant de compiler en live les fichiers adoc. Mais n’y a-t-il une solution plus simple encore?

Voici l’idée pour répondre au stockage et à la publication : l’outil Gitlab est utilisé comme serveur Git pour héberger les sources asciidoc et sa partie « wiki » (repository fils de celui des sources) être utilisé pour héberger les fichiers HTML générés. Sur un projet « MyProject », Gitlab propose une IHM d’administration des droits d’accès. Le projet fils « MyProject.wiki » héritera des mêmes droits. Si je vois le fichier adoc, je vois le fichier HTML. À noter que Gitlab propose une interprétation propre de la syntaxe asciidoc, sans toute fois rivaliser avec asciidoctor. Par exemple, Gitlab n’interprète de le code PlantUML.

Utilisons plutôt l’image Docker pour générer nos pages HTML. L’outil Open Source Jenkins propose le « Jenkins Worflow Plugin » qui permet de coder son workflow via le language Groovy. Cette solution est très intéressante car sort on peut sortir du schéma classique d’un job. Un job « Workflow Plugin » peut créer à la volée un conteneur Docker pour la génération de la documentation.

Voici un schéma explicatif d’un job Jenkins permettant de générer les pages HTML d’un wiki :

10- job Jenkins

On imagine maintenir un fichier index.asciidoc listant l’ensemble des pages du wiki. Ce job peut s’exécuter à la suite de tout changement sous Git des sources asciidoc.

11- fichier index.asciidoc

Cette solution permet d’avoir un wiki toujours à jour. Un projet de documentation doit être vu comme tout projet de développement, avec la mise en place d’une plateforme d’intégration continue (ici Jenkins) possédant des jobs validant régulièrement de la bonne bonne santé du projet : compilation, publication, …​

Au final

L’outillage asciidotor ne s’arrête pas là : génération de belles présentations RevealJS, DeckJS afin de remplacer notre ancien MsPowerpoint, écriture de sa JavaDoc en asciidoc à l’aide d’asciidoclet, …​

La présentation de tous ces outils permet d’introduit le sujet de « Living documentation », cher à Cyrille Martraire dans son livre du même nom (https://leanpub.com/livingdocumentation). La documentation doit vivre avec le code. Une partie doit être générée à partir du code, en définissant par exemple des annotations de type documentaire et en implémentant un parseur. Ce parseur pourrait générer de l’asciidoc! C’est exactement ce que propose l’outil Swagger pour la documentation des API REST. Cyrille illustre la possiblité de générer des diagrammes repésentant les différentes briques métier d’une application et leurs dépendances. Et pourquoi pas un diagramme de composants en PlantUML? Le sujet des tests d’acceptance, écrits via la syntaxe Gherkin, exécutés grâce à Cucumber, illustre un autre cas de documentation vivante.

La documentation a bien toute sa place dans le « delivery pipeline » d’une application. Elle profite de tout un ensemble d’outils Open Source et collaboratifs dès lors qu’on la considère comme du code. Vous retrouverez l’intégralité des ressources présentées (PlantUML, Docker, Groovy) sous GitHub : https://github.com/mrebiai/moijecodemadoc

Remerciements

Je tiens à remercier Benoit Prioux qui m’a initié à asciidoctor, Christian Chavez qui m’a sensibilisé à docker et à Rémi Goyard pour m’avoir convaincu de partager ce sujet au plus grand nombre.

Mehdi Rebiai

Mehdi Rebiai, architecte technique

0 commentaires

votre commentaire

Se joindre à la discussion ?
Vous êtes libre de contribuer !

Laisser un commentaire

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

Inscription newsletter

Ne manquez plus nos derniers articles !