GLO-4002 - Site du cours 2023

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 :

  1. l’un que vous pensez judicieux de régler et indiquez comment le régler
  2. 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

  1. Expliquez dans vos mots ce qu’est un domaine anémique.
  2. 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 ?
  3. Dans quel contexte devrait-on utiliser un domaine anémique ?