Éditeur de diagramme de classes Mermaid
Un diagramme de classes montre des types et leurs relations : ce qui contient quoi, ce qui hérite de quoi, ce qui dépend de quoi. Il convient quand la forme du code est le sujet — un modèle de domaine, une interface d'extension, un arbre d'héritage. Si vous voulez montrer ce qui se passe à l'exécution plutôt que la façon dont les types s'emboîtent, prenez un diagramme de séquence.
Un modèle de domaine de paiement
Trois types de relations en un seul diagramme : la composition pour les parties qui ne survivent pas au tout, l'héritage pour la hiérarchie des moyens de paiement, et une association ordinaire avec une multiplicité. Ici le sens est porté presque entièrement par les flèches ; les boîtes de classes sont presque accessoires.
classDiagram
class Commande {
+String reference
+EtatCommande etat
+Montant total()
+void ajouterLigne(Article a, int quantite)
}
class LigneDeCommande {
+Article article
+int quantite
+Montant sousTotal()
}
class MoyenDePaiement {
<<abstract>>
+autoriser(Montant montant) bool
}
class CarteBancaire {
+String quatreDerniers
+autoriser(Montant montant) bool
}
class VirementSepa {
+String iban
+autoriser(Montant montant) bool
}
class PrelevementAutomatique {
+String mandatRum
+autoriser(Montant montant) bool
}
Commande "1" *-- "1..*" LigneDeCommande : contient
Commande --> MoyenDePaiement : réglée par
MoyenDePaiement <|-- CarteBancaire
MoyenDePaiement <|-- VirementSepa
MoyenDePaiement <|-- PrelevementAutomatiqueExemples commentés
1. Une classe
`+` est public, `-` privé et `#` protégé. Un membre suivi de parenthèses est dessiné comme une méthode ; sans parenthèses, c'est un attribut.
classDiagram
class Utilisateur {
+String courriel
-String empreinteMotDePasse
+bool verifier(String candidat)
}2. Héritage et interfaces
`<|--` est l'héritage, à lire « celui de droite étend celui de gauche ». L'annotation `<<interface>>` est une étiquette et non un comportement, mais c'est elle qui rend le diagramme lisible.
classDiagram
class Depot {
<<interface>>
+chercher(String id) Entite
+enregistrer(Entite e) void
}
class DepotPostgres {
-Connexion connexion
+chercher(String id) Entite
+enregistrer(Entite e) void
}
class DepotEnMemoire {
-Map stockage
+chercher(String id) Entite
+enregistrer(Entite e) void
}
Depot <|.. DepotPostgres
Depot <|.. DepotEnMemoire3. Composition contre agrégation
La différence est la durée de vie. Le losange plein (`*--`) signifie que la partie meurt avec le tout : supprimez la facture et ses lignes disparaissent. Le losange creux (`o--`) signifie que la partie survit de son côté.
classDiagram
class Facture {
+String numero
}
class LigneFacture {
+String libelle
}
class Client {
+String raisonSociale
}
Facture "1" *-- "1..*" LigneFacture : composée de
Client "1" o-- "0..*" Facture : a émis4. Génériques
Les tildes donnent les paramètres de type : `Depot~Utilisateur~`. L'imbrication fonctionne aussi, ce qui est parfois nécessaire et rarement une bonne idée. Les accents passent sans problème dans un générique.
classDiagram
class Depot~T~ {
+chercher(String id) T
+tous() List~T~
}
class Cache~K, V~ {
+obtenir(K cle) V
+deposer(K cle, V valeur) void
}
class DepotUtilisateurs {
+chercherParCourriel(String courriel) Utilisateur
}
Depot~Utilisateur~ <|-- DepotUtilisateurs5. Notes et direction
`direction LR` place le diagramme de gauche à droite, ce qui convient d'ordinaire mieux à un arbre d'héritage que la disposition par défaut. Une note est le bon endroit pour la contrainte qui ne tient pas dans une boîte de classe.
classDiagram
direction LR
class JournalDEvenements {
+ajouter(Evenement e) void
+rejouer(String flux) List~Evenement~
}
class Instantane {
+int version
+byte[] contenu
}
JournalDEvenements --> Instantane : écrit tous les 100 événements
note for JournalDEvenements "En ajout seul. Les événements ne sont jamais modifiés ni supprimés."Référence de syntaxe du diagramme de classes
Les flèches de relation sont la partie qui mérite d'être apprise par cœur : ce sont elles qui distinguent un diagramme de classes d'un dessin de boîtes et de traits, et elles se lisent de droite à gauche d'une façon qui surprend longtemps.
| Syntaxe | Signification |
|---|---|
| classDiagram | Ouvre le diagramme. Sensible à la casse. |
| class Nom { ... } | Classe avec ses membres. L'accolade fermante va sur sa propre ligne. |
| +membre | Public. |
| -membre | Privé. |
| #membre | Protégé. |
| +methode(Type arg) TypeRetour | Une méthode — ce sont les parenthèses qui en font une. |
| <<interface>> / <<abstract>> | Stéréotype, écrit en première ligne dans la classe. |
| A <|-- B | Héritage : B étend A. |
| A <|.. B | Réalisation : B implémente l'interface A. |
| A *-- B | Composition : B ne survit pas à A. |
| A o-- B | Agrégation : B peut exister sans A. |
| A --> B | Association orientée. |
| A ..> B | Dépendance — A utilise B sans le détenir. |
| A "1" --> "0..*" B : libellé | Multiplicité à chaque extrémité et libellé de relation. |
| class Depot~T~ | Paramètre de type générique. |
| note for A "texte" | Note attachée à une classe. |
| direction LR | Change la direction du placement. |
Erreurs qui cassent un diagramme de classes
Reproduites avec Mermaid 11.12.2. Le diagramme de classes est plus indulgent que la plupart des types traités ici : plusieurs de ces erreurs se dessinent tranquillement et vous donnent la mauvaise image.
Ce que vous voyez
Parse error, se terminant par : got 'EOF_IN_STRUCT'
Pourquoi
Un corps de classe ouvert par `{` et jamais fermé. Pour une fois le nom du jeton aide vraiment : il signifie que le fichier s'est terminé alors qu'on était encore dans une classe.
Correction
Fermez l'accolade sur sa propre ligne.
classDiagram
class Commande {
+String referenceclassDiagram
class Commande {
+String reference
}Ce que vous voyez
Parse error, se terminant par : got 'ANNOTATION_END'
Pourquoi
Une flèche de diagramme de séquence employée dans un diagramme de classes. `->>` n'a aucun sens ici, et l'analyseur y entre assez loin pour produire un nom de jeton déroutant.
Correction
Utilisez une relation de classes : `-->` pour une association, `<|--` pour un héritage, `*--` pour une composition.
classDiagram
Commande ->> ClientclassDiagram
Commande --> Client : appartient àCe que vous voyez
No diagram type detected matching given configuration
Pourquoi
Mauvaise casse du mot-clé. `classdiagram` n'est pas `classDiagram`.
Correction
Mettez le D en majuscule.
classdiagram
class CommandeclassDiagram
class CommandeCe que vous voyez
La flèche pointe dans le sens contraire de ce que vous vouliez
Pourquoi
Les flèches de relation se lisent depuis la pointe vers l'arrière. `A <|-- B` signifie que B hérite de A, et non l'inverse. Écrite à l'envers, elle se dessine quand même : elle affirme simplement que votre classe de base étend sa propre sous-classe.
Correction
Lisez « l'extrémité éloignée étend l'extrémité pointue ». Mettez le parent à gauche de `<|--`.
classDiagram
CarteBancaire <|-- MoyenDePaiementclassDiagram
MoyenDePaiement <|-- CarteBancaireCe que vous voyez
Un attribut apparaît là où vous attendiez une méthode
Pourquoi
Les parenthèses sont la seule chose qui distingue une méthode d'un attribut. `+enregistrer` est un attribut nommé enregistrer ; `+enregistrer()` est une méthode. Les deux sont valides, donc rien ne vous prévient.
Correction
Ajoutez les parenthèses, puis le type de retour derrière si vous voulez le voir affiché.
classDiagram
class Depot {
+enregistrer
+chercher
}classDiagram
class Depot {
+enregistrer(Entite e) void
+chercher(String id) Entite
}Ce que vous voyez
Composition et agrégation se ressemblent au premier coup d'œil et disent le contraire
Pourquoi
`*--` et `o--` diffèrent d'un caractère et codent une vraie différence de sens : la partie peut-elle survivre au tout. Employer la mauvaise produit un diagramme techniquement bien formé et factuellement faux sur votre domaine.
Correction
Losange plein `*--` quand supprimer le parent supprime l'enfant. Creux `o--` sinon.
classDiagram
Commande o-- LigneDeCommande : contientclassDiagram
Commande *-- LigneDeCommande : contientNotes sur le rendu
Mesuré sur le Mermaid 11.12.2 qu'utilise ce site.
C'est le type qui grandit le plus vite en hauteur
Mesuré avec des classes à deux membres enchaînées par héritage : trois classes donnent un viewBox d'environ 176×548, quarante classes donnent 180×7726, soit environ 194 pixels de hauteur par classe, la croissance la plus raide des six types du site. Un diagramme de quarante classes dépasse les sept mille pixels de haut et devient inutilisable comme image unique. `direction LR` aide, mais au-delà d'une quinzaine de classes, la solution honnête est de découper le diagramme par domaine métier.
Le nombre de membres n'influe presque pas sur la largeur
La largeur est dictée par la signature de membre la plus longue, non par leur nombre. Une classe à vingt attributs courts n'est pas plus large qu'une classe à trois. Autrement dit : soyez généreux en membres et avare en classes, ce qui est exactement l'inverse de l'instinct. En français les signatures sont plus longues qu'en anglais, si bien que la largeur se joue souvent sur une seule méthode au nom descriptif.
Les accents et les apostrophes passent partout
Vérifié : `référence`, `empreinteMotDePasse` ou `JournalDEvenements` fonctionnent comme noms de classes et de membres, et les accents passent aussi à l'intérieur d'un générique. Inutile de dépouiller le modèle de ses accents pour qu'il se dessine. La seule vraie restriction vient du tilde, qui est de la syntaxe.
Les génériques utilisent des tildes, avec une conséquence
`Depot~T~` existe parce que les chevrons entreraient en collision avec le HTML des étiquettes. Cela implique aussi qu'un tilde littéral dans un nom de classe ou de membre sera lu comme le début d'un paramètre de type. C'est rare, mais franchement déroutant quand cela arrive.
Les étiquettes sont du HTML, donc l'export PNG redessine
Les étiquettes de classes sont dessinées dans un `<foreignObject>` du SVG, que les navigateurs refusent de rasteriser sur un canvas. L'export PNG de ce site échouait auparavant en silence et rendait un fichier SVG ; il redessine désormais d'abord le diagramme avec des étiquettes en texte SVG simple. Le PNG est correct et à taille réelle, avec une typographie très légèrement différente de celle de l'écran.
Quand un autre diagramme convient mieux
Si vous documentez une base de données et non un système de types, prenez un diagramme ER. La distinction compte : les diagrammes de classes modélisent le comportement et l'héritage, que les tables n'ont pas, et les diagrammes ER modélisent correctement les clés et les cardinalités, ce que les diagrammes de classes escamotent.
Si le diagramme se réduit à des boîtes reliées par `-->` sans aucun membre, ce que vous dessinez est une architecture et non un diagramme de classes. Un organigramme avec des sous-graphes sera plus beau et affirmera moins de choses.
Et si la liste des classes est générée depuis le code, demandez-vous si le diagramme ne devrait pas l'être aussi. Un diagramme de classes tenu à la main pour une base de code qui change chaque semaine est faux au bout d'un mois, et un diagramme faux coûte plus cher que pas de diagramme du tout.
Autres types de diagrammes
Écrit par Dominik Malsch · Dernière mise à jour: