Devoir Surveillé
Partie A - Langage de modélisation UML Question 1 - Diagramme de cas d'utilisation Un diagramme de cas d'utilisation modélise les interactions entre les utilisateurs (acteurs) et le système. Étant donné l'impossibilité de tracer informatiquement des figures sur ce support, voici la transcription exacte des éléments qui doivent figurer sur votre diagramme.
D'après le document Devoir Surveillé
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source
Modélisation et Programmation Objet · PDF · 3 pages · 2017
Afficher l'aperçu du document
Partie A - Langage de modélisation UML
Question 1 - Diagramme de cas d'utilisation
Un diagramme de cas d'utilisation modélise les interactions entre les utilisateurs (acteurs) et le système. Étant donné l'impossibilité de tracer informatiquement des figures sur ce support, voici la transcription exacte des éléments qui doivent figurer sur votre diagramme.
Acteurs identifiés :
- Administrateur (Acteur principal)
- Entraineur (Acteur principal)
- Entraineur du club adverse (Ce rôle peut être fusionné avec "Entraineur" ou modélisé comme un acteur héritant d'Entraineur, interagissant lors de la demande de match)
- Joueur (Acteur principal)
Associations entre Acteurs et Cas d'utilisation :
| Acteur | Cas d'utilisation associés |
|---|---|
| Administrateur | - Ajouter un joueur<br>- Mettre à jour un joueur<br>- Supprimer un joueur<br>- Ajouter un tournoi<br>- Ajouter un match<br>- Traiter une demande de match<br>- Visualiser les données sur un tournoi (avec matchs) |
| Entraineur | - Visualiser les données sur un tournoi (avec matchs)<br>- Proposer un match |
| Entraineur adverse | - Répondre à une demande de disponibilité (Confirmer disponibilité) |
| Joueur | - Visualiser les données sur un tournoi (avec matchs) |
Note sur le diagramme : Le cas d'utilisation "Visualiser les données sur un tournoi (avec matchs)" étant commun aux trois acteurs (Administrateur, Joueur, Entraineur), vous pouvez modéliser un acteur général "Utilisateur" regroupant ce cas, dont héritent les trois acteurs spécifiques, afin d'alléger le diagramme.
Question 2 - Diagramme d'activités
Le diagramme d'activités détaille le processus « Traitement d'une demande de match ». Il est recommandé d'utiliser des couloirs d'activités (swimlanes) pour montrer la responsabilité de chaque acteur.
Couloirs (Partitions) :
- Entraineur (Demandeur)
- Administrateur
- Entraineur adverse
Déroulement séquentiel des actions :
- [Nœud initial] placé dans le couloir de l'Entraineur.
- Action 1 (Entraineur) : "Envoyer une demande avec le nom du club adverse".
- Transition vers Administrateur.
- Action 2 (Administrateur) : "Recevoir la demande et contacter l'entraineur adverse".
- Transition vers Entraineur adverse.
- Action 3 (Entraineur adverse) : "Confirmer sa disponibilité" (Génère une réponse Favorable ou Défavorable).
- Transition vers Administrateur.
- Nœud de décision (Losange) : Évaluation de la réponse de l'entraineur adverse.
- Branche [Réponse Favorable] :
- Action 4a (Administrateur) : "Enregistrer un nouveau match".
- Action 5a (Système/Administrateur) : "Envoyer une notification automatique aux deux entraineurs".
- Transition vers le [Nœud final].
- Branche [Réponse Défavorable] :
- Action 4b (Système/Administrateur) : "Envoyer un message de refus à l'entraineur demandeur".
- Transition vers le [Nœud final].
- Branche [Réponse Favorable] :
Question 3 - Diagramme de classes d'analyse
Remarque : L'énoncé mentionne une « figure 1 - Diagramme de classes d'analyse à compléter » qui est absente du document source fourni. La conception ci-dessous reconstitue logiquement le diagramme de classes complet sur la base des règles de gestion dictées par le texte.
Classes et Attributs :
- Membre : Identifiant (ID), nom, prenom.
- Joueur (hérite de Membre) : taille, poids.
- Entraineur (hérite de Membre) : anneesExperience.
- Club : code.
- Tournoi : numeroUnique, nom, dateDebut, dateFin, adresse, type.
- Match : numeroUnique, date, duree.
- HistoriqueJoueur (Classe-association entre Joueur et Club) : periode, salaire.
Relations et Multiplicités :
- Héritage :
JoueuretEntraineurhéritent de la classe mère abstraiteMembre. - Association Joueur - Club (Jouer dans) :
- Un Joueur joue dans un à plusieurs clubs durant sa carrière :
1..*(côté Club). - Un Club contient au maximum 29 joueurs :
0..29(côté Joueur). - Classe-association : Le texte indique "durant sa carrière... pendant une période de temps et avec un salaire bien déterminé". Ces informations (période, salaire) ne dépendent ni du joueur seul, ni du club seul, mais de la relation historique entre les deux. Il faut donc une classe-association liée à cette relation.
- Un Joueur joue dans un à plusieurs clubs durant sa carrière :
- Association Entraineur - Club (Diriger/Entrainer) :
- Un Club a un seul entraineur :
1..1(côté Entraineur). - Un Entraineur entraîne un club (à la fois) :
0..1ou1..1(côté Club).
- Un Club a un seul entraineur :
- Association Tournoi - Match (Contenir) :
- Un Tournoi contient plusieurs matchs :
1..*(côté Match). - Un Match appartient à un tournoi :
1..1(côté Tournoi).
- Un Tournoi contient plusieurs matchs :
Partie B - JAVA
Note préliminaire : Les règles exigent que le code soit exécutable. L'énoncé précise que Joueur a ses getters/setters implémentés et que la classe Entraineur est déjà implémentée. Pour garantir la compilation du code ci-dessous (règle 4), une implémentation minimale de Entraineur est incluse, et les attributs de Membre sont déclarés protected pour permettre l'accès par héritage et au sein du même paquet.
Question I - Implémentation de la classe Membre
public class Membre {
// Déclarés en protected pour être accessibles par les classes filles (Joueur, Entraineur)
protected int id;
protected String nom;
protected String prenom;
// Uniquement un constructeur paramétré
public Membre(int id, String nom, String prenom) {
this.id = id;
this.nom = nom;
this.prenom = prenom;
}
// Getters et Setters uniquement pour l’attribut identifiant
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// La méthode toString
@Override
public String toString() {
return "ID: " + id + ", Nom: " + nom + ", Prénom: " + prenom;
}
// La méthode equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Membre membre = (Membre) o;
// Deux membres sont égaux s’ils ont le même identifiant et le même nom
return this.id == membre.id &&
this.nom != null &&
this.nom.equals(membre.nom);
}
}
Question II - Implémentation de la classe Joueur
public class Joueur extends Membre {
private float taille;
private float poids;
public Joueur(int id, String nom, String prenom, float taille, float poids) {
super(id, nom, prenom); // Appel du constructeur de la classe mère
this.taille = taille;
this.poids = poids;
}
// Les getters et setters sont supposés implémentés selon l'énoncé
public float getTaille() { return taille; }
public void setTaille(float taille) { this.taille = taille; }
public float getPoids() { return poids; }
public void setPoids(float poids) { this.poids = poids; }
@Override
public String toString() {
return super.toString() + ", Taille: " + taille + ", Poids: " + poids;
}
}
Code additionnel pour la compilation des parties suivantes, modélisant la classe Entraineur mentionnée comme "déjà implémentée" par l'énoncé :
public class Entraineur extends Membre {
private int anneesExperience;
public Entraineur(int id, String nom, String prenom, int anneesExperience) {
super(id, nom, prenom);
this.anneesExperience = anneesExperience;
}
}
Question III - Implémentation de la classe Club et de l'Exception
Afin que l'exception personnalisée demandée à la question III.6 puisse être compilée, nous devons d'abord la définir.
public class PoidsException extends Exception {
public PoidsException(String message) {
super(message);
}
}
Voici l'implémentation complète de la classe Club, intégrant les 6 sous-questions.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Club {
private String code;
private List<Membre> membres;
public Club(String code) {
this.code = code;
this.membres = new ArrayList<>();
}
// 1. La méthode ajouter
public void ajouter(Membre membre) {
// Un membre ne peut être affecté deux fois (utilise la méthode equals de Membre)
if (membres.contains(membre)) {
return;
}
// Vérification des contraintes selon le type de membre
if (membre instanceof Entraineur) {
// Un club ne peut contenir qu'un seul entraineur
for (Membre m : membres) {
if (m instanceof Entraineur) {
System.out.println("Opération refusée : Le club possède déjà un entraineur.");
return;
}
}
} else if (membre instanceof Joueur) {
// Un club peut contenir au maximum 29 joueurs (contrainte textuelle de la partie A)
int compteurJoueurs = 0;
for (Membre m : membres) {
if (m instanceof Joueur) {
compteurJoueurs++;
}
}
if (compteurJoueurs >= 29) {
System.out.println("Opération refusée : Le club a atteint sa limite de 29 joueurs.");
return;
}
}
membres.add(membre);
}
// 2. La méthode supprimer
public void supprimer(Membre membre) {
membres.remove(membre);
}
// 3. La méthode toString (code du club et uniquement la liste de ses Joueurs)
@Override
public String toString() {
StringBuilder description = new StringBuilder();
description.append("Code du Club: ").append(code).append("\nListe des joueurs:\n");
for (Membre m : membres) {
if (m instanceof Joueur) {
description.append(m.toString()).append("\n");
}
}
return description.toString();
}
// 4. La méthode afficherTailles (affiche uniquement les tailles des joueurs)
public void afficherTailles() {
for (Membre m : membres) {
if (m instanceof Joueur) {
Joueur j = (Joueur) m;
System.out.println("Taille: " + j.getTaille());
}
}
}
// 5. La méthode supprimerJoueurs par nom
public void supprimerJoueurs(String nom) {
// L'utilisation d'un Iterator est indispensable pour supprimer des éléments
// d'une collection tout en la parcourant, évitant ainsi une ConcurrentModificationException.
Iterator<Membre> it = membres.iterator();
while (it.hasNext()) {
Membre m = it.next();
// L'attribut 'nom' est accessible ici car il a été déclaré 'protected' dans Membre
if (m instanceof Joueur && m.nom != null && m.nom.equals(nom)) {
it.remove();
}
}
}
// 6. La méthode moyennePoids
public float moyennePoids() throws PoidsException {
float sommePoids = 0;
int nombreJoueurs = 0;
for (Membre m : membres) {
if (m instanceof Joueur) {
sommePoids += ((Joueur) m).getPoids();
nombreJoueurs++;
}
}
if (nombreJoueurs == 0) {
return 0.0f;
}
float moyenne = sommePoids / nombreJoueurs;
if (moyenne > 80.0f) {
throw new PoidsException("Poids des joueurs trop élevé");
}
return moyenne;
}
}
Méthode
Face à ce type de devoir surveillé, la réussite repose sur la lecture rigoureuse des consignes et la compréhension des liens invisibles entre les questions :
- Repérage des contraintes cardinales en UML : Dès la lecture du texte introductif, encadrez les mots exprimant des quantités ("au maximum 29 joueurs", "un seul entraineur", "plusieurs clubs"). Ces mots dictent les multiplicités de votre diagramme de classes et se traduisent plus tard directement par des conditions
ifdans votre code (comme dans la méthodeajouter()de la classeClub). - Identification des héritages : Quand le texte dit "Un membre est caractérisé par... Un joueur par... Un entraineur par...", il décrit une structure d'héritage classique. En Java, cela implique l'utilisation du mot-clé
extendset le bon paramétrage de l'appelsuper()dans le constructeur de la classe fille. - Respect strict des conventions (Encapsulation) : L'énoncé précise "Les Getters et les Setters ne sont à implémenter que si leur demande est explicite". C'est un piège classique de conception. Il vous interdit de créer un
getNom()dansMembre. Par conséquent, pour accéder au nom danssupprimerJoueurs(String nom)de la classeClub, l'attributnomdoit avoir une portée (visibilité)protectedoupackage-private, et nonprivate. - Gestion des collections en Java : Lorsqu'on vous demande de supprimer des éléments d'une liste sous une certaine condition (Question III.5), il est déconseillé d'utiliser une boucle
forou unforeach, car modifier une liste pendant son parcours déclenche une erreur d'exécution (ConcurrentModificationException). Le réflexe doit être l'utilisation de l'objetIterator.
Commentaires
Aucun commentaire pour le moment. Posez la première question.