Exemple de diagramme de classes UML : modéliser une plateforme de cours en ligne

Un diagramme de classes UML commenté pour une plateforme de cours en ligne : classes, visibilité, multiplicité, association, composition, héritage ou interface.

· Fondateur et développeur

Publié le

Exemple de diagramme de classes UML : modéliser une plateforme de cours en ligne

La plupart des types de diagrammes UML vivent dans les manuels. Le diagramme de classes est celui que les ingénieurs dessinent encore : une image des choses dont parle un système, de ce que chacune contient, de ce qu'elle sait faire et de la façon dont elles sont liées. Bien dessiné, il clôt les débats sur le modèle de domaine avant que quiconque écrive une migration ou une API.

Cet article construit un diagramme de classes UML pour une petite plateforme de cours en ligne, une décision à la fois, et explique la notation au fil de l'eau : visibilité, multiplicité, association, composition, héritage et interfaces. Il se termine par les erreurs qui rendent les diagrammes de classes inutiles et par un bref aperçu du passage du diagramme au code.

Quand le diagramme de classes est la bonne image

La spécification UML 2.5.1 répartit ses diagrammes entre diagrammes de structure et diagrammes de comportement. Le diagramme de classes est un diagramme de structure : il montre des types, leurs attributs et opérations, et les relations entre eux, sans aucune notion de temps.

Question à laquelle vous devez répondre Diagramme
Quels concepts existent, ce qu'ils savent, comment ils sont liés Diagramme de classes
Comment les données sont stockées : tables, clés, clés étrangères Diagramme ER
Ce qui se passe, et dans quel ordre, entre des participants Diagramme de séquence
Par quels états passe un objet Diagramme d'états-transitions

Un diagramme de classes mérite sa place pour un modèle de domaine, pour les types publics d'une bibliothèque ou pour une conception que vous vous apprêtez à réaliser. Il ne la mérite pas comme inventaire de toutes les classes d'un dépôt : un IDE le montre mieux, et l'image est périmée au commit suivant.

La notation en deux tableaux

Une classe est une boîte avec jusqu'à trois compartiments : le nom, les attributs et les opérations. Chaque compartiment peut être omis.

Élément Notation Signification
Classe abstraite Nom en italique, ou {abstract} Ne peut pas être instanciée ; les sous-classes la complètent
Interface «interface» au-dessus du nom Un contrat d'opérations
Visibilité + public, - private, # protected, ~ package Qui peut utiliser la caractéristique
Attribut name: Type [multiplicity] = default Les données que l'objet contient
Opération name(param: Type): ReturnType Le comportement que l'objet offre
Caractéristique statique Soulignée Appartient à la classe, pas à une instance

Les relations sont des lignes entre les classes, et ce sont leurs extrémités qui portent l'essentiel du sens :

Relation Ligne À lire comme
Association Ligne pleine ; une flèche ouverte marque une extrémité navigable « est lié à »
Agrégation Ligne pleine, losange vide côté tout « regroupe » ; les parties vivent seules
Composition Ligne pleine, losange plein côté tout « est fait de » ; les parties disparaissent avec le tout
Généralisation Ligne pleine, triangle vide côté parent « est une sorte de »
Réalisation Ligne pointillée, triangle vide côté interface « implémente »
Dépendance Ligne pointillée, flèche ouverte côté cible « utilise » ; un changement de la cible peut casser la source

La composition est la relation stricte. D'après la spécification, un objet partie appartient à au plus un composite à la fois, et lorsque le composite est supprimé, ses parties le sont avec lui. L'agrégation partagée, le losange vide, est la relation floue : la spécification elle-même indique que sa sémantique précise varie selon le domaine d'application et le modélisateur. Ne l'utilisez que si votre équipe s'accorde sur son sens ; une simple association dit la même chose avec moins de débats.

La multiplicité

La multiplicité indique combien d'objets peuvent se trouver à une extrémité d'une association : 1 pour exactement un, 0..1 pour optionnel, * (identique à 0..*) pour un nombre quelconque, 1..* pour au moins un, et des intervalles comme 2..5. Écrivez-la à l'extrémité, à côté de la classe qu'elle compte. Lisez Course 1 — 1..* Module ainsi : « un cours a un ou plusieurs modules, et chaque module appartient à exactement un cours. »

Les multiplicités manquantes sont la raison la plus fréquente pour laquelle un diagramme de classes lance des débats au lieu de les clore. Dans l'exemple ci-dessous, chaque association a ses deux extrémités renseignées.

L'exemple : une plateforme de cours en ligne

Partez de phrases simples, pas de boîtes :

  1. Les formateurs publient des cours. Un cours a un ou plusieurs formateurs.
  2. Un cours est fait de modules ordonnés, et un module de leçons ordonnées.
  3. Une leçon est une vidéo, un quiz ou un devoir.
  4. Les quiz et les devoirs sont notés ; les vidéos ne le sont pas.
  5. Les apprenants s'inscrivent à des cours. Une inscription suit la progression et contient les rendus de l'apprenant.
  6. Un apprenant qui termine un cours obtient un certificat pour cette inscription.
  7. Les cours sont classés en catégories, et un cours peut appartenir à plusieurs.

Les utilisateurs : une classe, deux rôles

Le premier réflexe est de faire de Student et Instructor des sous-classes de User. Cela casse dès qu'un formateur suit le cours de quelqu'un d'autre : dans la plupart des langages de programmation, un objet garde la même classe toute sa vie ; il ne peut donc pas être les deux, ni changer plus tard. Modélisez plutôt les rôles comme des associations : un User enseigne des cours, et un User possède des inscriptions. Réservez l'héritage à ce qui est une sorte de quelque chose toute sa vie, comme un quiz qui est une sorte de leçon.

La composition quand les cycles de vie sont liés

Un module n'a pas de sens hors de son cours, ni une leçon hors de son module. Supprimer un cours supprime les deux. C'est une composition : un losange plein sur Course et sur Module, avec 1 côté tout. Les catégories sont différentes. Supprimer la catégorie « Data engineering » ne doit pas supprimer ses cours, donc Category vers Course est une agrégation avec * aux deux extrémités.

L'héritage plus une interface

Lesson est abstraite ; VideoLesson, Quiz et Assignment héritent de son titre et de sa position. La notation traverse cet arbre : les quiz et les devoirs sont notés, les vidéos non, et une évaluation par les pairs ajoutée l'an prochain pourrait être notée sans être une leçon du tout. C'est une interface, Gradable, réalisée par Quiz et Assignment. GradingService dépend de Gradable, pas des classes concrètes, et la flèche de dépendance en pointillé dit exactement cela.

Une association qui a ses propres données

Enrollment se place entre User et Course. UML a une notation dédiée pour cela, la classe-association, rattachée à la ligne par un trait pointillé. La plupart des équipes la dessinent plutôt comme une classe ordinaire avec deux associations, car elle a sa propre identité, ses données et son comportement : la date d'inscription, la progression, les rendus et au plus un certificat.

Course est composé de Modules, eux-mêmes composés de Lessons. VideoLesson, Quiz et Assignment héritent de la classe abstraite Lesson ; Quiz et Assignment réalisent Gradable. Les utilisateurs enseignent et s'inscrivent via Enrollment, qui porte des Submissions et un Certificate optionnel.

32 composants · 16 connexions

Ouvrir dans Archboard
Contenu du diagramme
  • Category
  • Course
  • User
  • Module
  • Enrollment
  • Certificate
  • Lesson
  • Submission
  • VideoLesson
  • Quiz
  • Assignment
  • Gradable
  • GradingService
  • groups
  • teaches
  • enrolls
  • for
  • earns
  • holds
  • answers
  • «use»
Un diagramme de classes UML pour une plateforme de cours en ligne : des cours composés de modules et de leçons, trois types de leçons sous une classe abstraite, les travaux notés derrière une interface et des inscriptions qui relient utilisateurs et cours.

Comment le lire :

  • En haut à gauche, le catalogue. Course est composé de Module, lui-même composé de Lesson, avec des losanges pleins côté tout. Category regroupe des cours avec un losange vide.
  • En bas à gauche, les types de leçons. Lesson est abstraite. VideoLesson, Quiz et Assignment pointent vers elle avec des triangles vides.
  • À droite, l'apprentissage. Un User enseigne des cours, avec 1..* formateurs par cours, et possède un nombre quelconque d'inscriptions, chacune pour exactement un cours. Un Enrollment contient des rendus et donne droit à au plus un Certificate.
  • En bas à droite, la notation. Quiz et Assignment réalisent Gradable avec des lignes pointillées et des triangles vides. Chaque Submission répond à un élément noté, et GradingService ne dépend que de l'interface.

Erreurs courantes

  • Toutes les classes de la base de code. Dix à quinze classes par diagramme est une bonne limite. Découpez un modèle plus grand par domaine, ou montrez le reste sous forme de noms sans compartiments.
  • Des getters et setters comme opérations. Listez les opérations qui ont un sens métier, comme publish() ou enroll(), pas les accesseurs.
  • Des tables dessinées comme des classes. Des attributs comme courseId ont leur place dans le diagramme ER. Dans un diagramme de classes, la ligne d'association est la référence.
  • L'héritage pour les rôles. Si un objet peut acquérir ou perdre le rôle, c'est une association, pas une sous-classe.
  • Des losanges sans signification. Si personne ne peut dire ce que la suppression du tout fait aux parties, utilisez une simple association.
  • Des détails d'implémentation au niveau du domaine. Laissez de côté les annotations de framework, les DTO et les repositories, sauf si le diagramme porte sur eux.

Du diagramme au code

Le diagramme se traduit directement en code. En TypeScript :

interface Gradable {
  maxScore(): number;
  autoGrade(submission: Submission): Score | null;
}

abstract class Lesson {
  constructor(public title: string, public position: number) {}
}

class Quiz extends Lesson implements Gradable {
  questions: Question[] = [];
  maxScore(): number {
    return this.questions.length;
  }
  autoGrade(submission: Submission): Score | null {
    return submission.scoreAgainst(this.questions);
  }
}

class Course {
  private readonly modules: Module[] = []; // composition: owned and removed with the course
  categories: Category[] = []; // aggregation: categories exist on their own

  addModule(title: string): Module {
    const created = new Module(title, this.modules.length);
    this.modules.push(created);
    return created;
  }
}

La composition devient de la possession : le cours crée ses modules, et rien ne maintient un module en vie une fois le cours disparu. L'agrégation devient une référence vers un objet doté de son propre cycle de vie. Quand le code et le diagramme divergent, mettez à jour le diagramme dans la même pull request ; c'est bien plus simple quand le diagramme est un lien plutôt qu'une capture d'écran, comme l'explique l'article des diagrammes d'architecture qui ne se périment pas.

Le construire dans Archboard

  1. Connectez-vous avec Google ou GitHub et créez un diagramme.
  2. Depuis le pack UML, ajoutez une Classe pour chaque concept et écrivez les attributs et les opérations à raison d'un par ligne. Réglez le stéréotype de Lesson sur abstract.
  3. Ajoutez une Interface pour Gradable avec ses deux opérations.
  4. Reliez les classes. Réglez l'extrémité de flèche côté tout sur Losange plein pour la composition et sur Losange pour l'agrégation, et sur Triangle côté parent pour l'héritage. Dessinez la réalisation en ligne pointillée avec un Triangle côté interface, et la dépendance en ligne pointillée avec une Flèche ouverte.
  5. Placez les multiplicités en texte à côté de chaque extrémité, et nommez les associations, comme « teaches », dans l'étiquette du lien.
  6. Ajoutez une Note UML pour les décisions, par exemple pourquoi les rôles sont des associations.

L'exemple utilise 13 nœuds de diagramme et reste dans les limites de l'offre Free. Avec un agent IA connecté via MCP, vous pouvez décrire les exigences et le laisser esquisser les classes, puis corriger vous-même les multiplicités.

FAQ

Quelle est la différence entre un diagramme de classes et un diagramme d'objets ? Un diagramme de classes montre des types et les règles qui les lient. Un diagramme d'objets montre des instances précises à un instant donné, avec leurs valeurs et leurs liens ; il sert à vérifier un diagramme de classes sur un exemple réel.

Quelle est la différence entre agrégation et composition ? Avec la composition, une partie appartient à un seul tout et disparaît avec lui. Avec l'agrégation, les parties peuvent exister seules et être partagées ; son sens exact est laissé au modélisateur, si bien que beaucoup d'équipes lui préfèrent une simple association.

Un diagramme de classes doit-il correspondre exactement au code ? Un modèle de domaine doit correspondre aux concepts et aux relations, pas à chaque champ et chaque méthode. Gardez-le à un niveau qu'une cheffe de produit et un ingénieur peuvent tous deux lire.

En quoi un diagramme de classes diffère-t-il d'un diagramme de composants C4 ? Un diagramme de composants C4 montre des briques déployables et leurs responsabilités. Un diagramme de classes descend d'un niveau, jusqu'aux types qu'elles contiennent ; voir l'exemple de diagramme du modèle C4.

Puis-je générer un diagramme de classes automatiquement à partir du code ? Beaucoup d'IDE le permettent, mais le résultat montre toutes les classes et se lit mal. Dessinez le modèle de domaine à la main ou avec un agent IA, et limitez-le aux classes qui comptent.

Commencez gratuitement — un siège, sans carte bancaire.

Articles associés

← Retour au blog

Ouvrez un canevas en une minute

Connectez-vous avec Google ou GitHub. Gratuit pour un siège. Passez à un forfait supérieur quand l’équipe vous rejoint.