Temps estimé: 30 minutes
Recap 4 : Anciens examens
Voici des questions sur le TDA et le SRP qui proviennent d'anciens examens.
Les réponses ne seront pas données, mais n'hésitez pas à vous valider entre vous, ou à nous écrire si vous avez des questions.
Question 1
En considérant la classe suivante
public class SiegeController{
public ReponseSiegeDto trouverMeilleursSiege(DemandeSiegeDto demande) {
// 1−Créer la bonne classe dans le vol
ClasseVol classeVol;
if (demande.classeVol == "E") {
classeVol = newClasseEconomie(volId);
// Ignorez comment la classe obtient les sièges
// pas important pour l’examen
} else if (demande.classeVol == "A") {
classeVol = newClasseAffaires(volId);
} else {
throw new RuntimeException("Classenonsupportée");
}
// 2−Trouver les siège
List<Siege> siegesTrouves = classeVol.trouverMeilleursSieges(demande);
// 3−Préparation de la réponse
if (siegesTrouves.isEmpty()) {
throw new PasDeSiegeTrouve();
}
return ReponseSiegeDto.from(siegesTrouves);
}
}
Expliquez où et comment le SRP n'est pas respecté
ATTENTION, nous ne cherchons pas une réponse théorique en répétant l’énoncé du principe. Nous voulons une explication concrète qui explique ce qui vous amène à penser que le principe n’est pas respecté dans CE CAS.
Question 2
Considérant le code suivant
public class GroupeClasse {
private List<Travail> travaux = new ArrayList<>();
private List<Etudiant> etudiantsInscrits = new ArrayList<>();
public void ajouterTravail(Travail travail) {
this.travaux.add(travail);
}
public void inscrireEtudiant(Etudiant etudiant) {
etudiantsInscrits.add(etudiant);
}
/*
* 1. Pour tous les travaux > Pour tous les etudiants ayant remis
* > Inscrire son resultat a son dossier
* Le resultat est pondere ( % que vaut le travail)
* > Rien inscrire si pas remis
* 2. Une fois tous resultats inscrits aux dossiers
* > On fixe la cote en fonction de la note
* totale de tous les travaux (sommes des notes ponderees)
*/
public void publierNotes() {
if (travaux.size() == 0) {
return;
}
Map<Etudiant, Double> notesPondereeParEtudiant = new HashMap<>();
for (Travail travail : travaux) {
for (Remise remise : travail.getRemises()) {
Etudiant etudiantRemise = remise.getEtudiant();
double note = remise.getNote();
double ponderation = travail.getPonderation();
double notePonderee = note * ponderation;
etudiantRemise.getDossier().inscrireResultatTravail(travail.getCode(),
notePonderee);
// Pour l’etudiant ayant soumis cette remise, on cummule ses notes
// totales de tous les travaux dans une grande
// Map d "Etudiant => Note_commulee"
notesPondereeParEtudiant.merge(etudiantRemise, notePonderee, (x, y) -> x + y);
}
}
// Pour chaque etudiant, il faut fixer sa cote a partir
// de la somme des notes ponderees de tous ses travaux remis
for (Etudiant etudiant : etudiantsInscrits) {
double total = notesPondereeParEtudiant.getOrDefault(etudiant, 0.0);
etudiant.getDossier().fixerCote(total);
}
}
}
class Travail {
private String code;
private Map<Etudiant, Remise> remises = new HashMap<>();
private double ponderation;
Travail(String code, double ponderation) {
this.code = code;
this.ponderation = ponderation;
}
public List<Remise> getRemises() {
return new ArrayList<>(remises.values());
}
public void addRemise(Remise remise) {
remises.put(remise.getEtudiant(), remise);
}
public String getCode() {
return code;
}
public double getPonderation() {
return ponderation;
}
}
class Remise {
private double note;
private Etudiant etudiant;
Remise(double note, Etudiant etudiant) {
this.note = note;
this.etudiant = etudiant;
}
public double getNote() {
return note;
}
public Etudiant getEtudiant() {
return etudiant;
}
}
class Etudiant {
private String ni;
private DossierEtudiantElectronique dossier;
public Etudiant(String ni, DossierEtudiantElectronique dossier) {
this.ni = ni;
this.dossier = dossier;
}
public String getNI() {
return ni;
}
public DossierEtudiantElectronique getDossier() {
return dossier;
}
}
interface DossierEtudiantElectronique {
public void inscrireResultatTravail(String code, double notePonderee);
public void fixerCote(double noteFinale);
public void publier();
}
class Registraire {
private List<DossierEtudiantElectronique> etudiants = new ArrayList<>();
public void publierCotes() {
for (DossierEtudiantElectronique dossierEtudiant : etudiants) {
dossierEtudiant.publier();
}
}
}
Ce code fait preuve d’obsession des primitives (Primitive Obsession).
Donnez 2 cas d’obsession :
- l’un que vous pensez judicieux de régler et indiquez comment le régler
- un 2e que vous laisseriez tel quel (ne pas corriger) et pourquoi
Question 3
En vous référant au code de la question 2, la méthode publierNotes
de la classe GroupeClasse
ne respecte pas à plusieurs endroits le Tell don’t Ask (TDA).
Proposer un réusinage afin de respecter le TDA.
Instructions :
- Vous devez préserver exactement le même comportement final.
- Vous pouvez cependant créer de nouvelles méthodes ou modifier des méthodes dans les classes existantes.
- Vous de devez PAS toucher à l’interface DossierEtudiantElectronique
- Vous ne devez PAS changer la signature de la méthode d’entrée GroupeClasse::publierNotes()
- Indice : il n’est pas nécessaire d’introduire de nouvelles classes.
Question 4
- Expliquez dans vos mots ce qu’est un domaine anémique.
- Pourquoi est-ce un problème dans un domaine « riche » où la logique d’affaires est complexe ? Quelle serait la conséquence de créer un tel domaine anémique dans ce contexte ?
- Dans quel contexte devrait-on utiliser un domaine anémique ?