Afficher des diagrammes de classes avec PlantUML
Quand nous utilisons de la programmation orientée objet, c'est utile de pouvoir voir le diagramme de classes. Dans cet article, je vais vous montrer comment utiliser PlantUML pour générer des diagrammes de classes et un exemple de script pour trouver la hiérarchie de classes d'un projet et générer son diagramme de classes. Je fais ça sur Linux.
PlantUML
PlantUML est un outil pour générer des diagrammes. Cela utilise un code lisible par des êtres humains pour spécifier les diagrammes ce qui rend cela pratique pour en générer via des scripts.
Par exemple pour afficher le diagramme de classes avec ChildClass
(classe fille) héritant de MotherClass
(classe mère), nous pouvons utiliser le morceau de code suivant.
@startuml
MotherClass <|-- ChildClass
@enduml
PlantUML génère cette image.

PlantUML peut être utilisé pour générer d'autres types de diagramme comme des diagrammes de séquences, des diagrammes d'activité... Regardez leur site et leur documentation pour plus d'information.
Laissez-moi vous montrer comment intégrer PlantUML dans un script pour facilement découvrir la hiérarchie de classes utilisée dans hxWidgets.
Afficher le diagramme de classes de la bibliothèque hxWidgets
hxWidgets est un port de wxWidgets en Haxe. hxWidgets a été développé par l'équipe derrière HaxeUI.
Si vous n'avez rien compris à ce que je viens de dire: Haxe est un langage de programmation orienté objet, le code source peut être compilé en d'autres langages (JavaScript, C++, PHP...) et donc peut être utilisé pour faire des applications web mais aussi des logiciels natifs. wxWidgets est une bibliothèque C++ pour programmer des interfaces comme le sont GTK et QT. hxWidgets est un port de wxWidgets en Haxe et peut être utilisé à l'intérieur de HaxeUI pour faire des interfaces natives (sinon des moteurs de jeux vidéo sont utilisés) en Haxe.
Récupérer le code source de hxWidgets
Clonez simplement le dépôt officiel.
git clone https://github.com/haxeui/hxWidgets
Trouver les définitions de classe
En Haxe, les classes sont définis de cette manière.
class ChildClass extends MotherClass implements Interface {
// Contenu de la classe
}
Utilisons la commande grep
pour trouver les définitions de classe.
La première chose que l'on veut faire est d'être sûrs que nous recherchons le mot entier class
et non la chaîne de caractères class
. Pour cela nous utilisons les atomes d'expressions rationnelles (regex atoms) \<
qui indique le début d'un mot et \>
qui indique la fin d'un mot. Si vous êtes un utilisateur de Vim, quand vous utilisez en normal mode la commande *
, Vim utilise ces atomes (regardez en bas de l'écran ou vérifier l'historique de recherche avec la commande :history search
). Ici un exemple.
$ cat file.txt
xxxxxxxxxxxxxxxxx
xxxxx class xxxxx
xxxxxxclassxxxxxx
xxxxxxxxxxxxxxxxx
$ grep --extended-regexp "class" file.txt
xxxxx class xxxxx
xxxxxxclassxxxxxx
$ grep --extended-regexp "\<class\>" file.txt
xxxxx class xxxxx
Chercher pour ce pattern dans le dépôt de code source nous renvoie ce résultat. Je vous montre seulement les parties intéressantes.
$ grep --recursive \
--no-filename \
--extended-regexp \
"\<class\>" hxWidgets/src/hx/widgets/
class OwnerDrawnPanel extends Panel {
class ClientDC extends WindowDC {
class ColourData {
class ArrayString { //extends WxArray<String> {
class MouseEvent extends Event implements MouseState {
class BookCtrlBase extends Control implements WithImages {
return autoConvert(win); // lets auto convert the class so it can be used with casts
list.push(autoConvert(win)); // lets auto convert the class so it can be used with casts
return autoConvert(win); // lets auto convert the class so it can be used with casts
Nous avons encore trop d'informations (voir les lignes surlignées). Nous devrions supprimer les sections commentées dans la définition de classe et exclure les lignes où le mot class
apparaît seulement en commentaire.
Améliorons notre expression rationnelle en utilisant ^\<class\>[^\{]+\{
qui signifie que nous voulons uniquement les lignes commençant par le mot class
et que nous prenons jusqu'au premier {
qui apparaît. Nous utilisons l'option --only-matching
pour avoir seulement la partie capturée. La commande est maintenant:
grep --recursive \
--no-filename \
--only-matching \
--extended-regexp \
"^\<class\>[^\{]+\{" hxWidgets/src/hx/widgets/
Convertir le résultat en code PlantUML
Pour convertir le résultat en code PlantUML, nous créons un script Python def2plantuml.py
. J'aurais pu utiliser AWK ou faire un script shell utilisant sed
mais la version en Python était plus rapide à écrire et plus simple à lire.
import sys
import re
"""
Convertie la liste de définitions de classe en diagrammes de classes PlantUML.
"""
print("@startuml")
print("skinparam groupInheritance 2")
for line in sys.stdin:
# Supprime les nouvelles lignes
clean = line.strip()
# Supprime le { à la fin
clean = re.sub(r" {.*", "", clean)
# Supprime le mot "class" au début de la ligne
clean = re.sub(r"^class ", "", clean)
# Nous ne sommes intéressés que par la hiérarchie de classes
# donc nous supprimons la définition d'implémentation d'interface.
clean = re.sub(r" implements.*", "", clean)
# Si cela hérite d'une classe, afficher le lien
split = clean.split(" extends ")
if len(split) == 1:
print("class " + split[0])
else:
print(split[1] + " <|-- " + split[0])
print("@enduml")
Tout regrouper ensemble
Nous créons ensuite un script shell nommé create-class-diagram
et nous utilisons ce que nous avons fait précédemment.
#!/bin/sh
# Génère le diagramme de classes du paquet hx.widgets
grep --recursive \
--no-filename \
--only-matching \
--extended-regexp \
"^\<class\>[^\{]+\{" hxWidgets/src/hx/widgets/ |
sort |
python3 def2plantuml.py |
plantuml -pipe -tsvg > diagram.svg
# Ici utilise Inkscape 0.92.5 où l'option "--pipe" n'est pas présente
inkscape --export-pdf="diagram.pdf" diagram.svg
rm diagram.svg
Dans ce script nous listons les définitions de classe avec notre commande grep
et nous mettons tout dans l'ordre alphabétique. Nous envoyons le résultat à notre script de conversion. Nous envoyons ensuite le résultat à plantuml
pour qu'il puisse exporter ce résultat dans un fichier SVG nommé diagram.svg
.
Nous utilisons Inkscape pour créer un fichier PDF pour qu'il soit plus simple de rechercher une classe. Si vous utilisez une version supérieure à 0.92.5 peut-être que vous avec l'option --pipe
et que vous n'avez pas besoin de créer diagram.svg
. Nous sauvegardons le tout dans diagram.pdf
et voici le résultat.

Ce n'est peut-être pas le plus beau diagramme mais au moins ça fait le boulot.