GLO-4002 - Site du cours 2023

Temps estimé: 30 minutes

Série d'exercices sur le SRP

Question 1

Décrivez le SRP dans vos mots.

Une classe/fonction/module ne doit avoir qu’une seule responsabilité, c'est-à-dire qu’une seule raison de changer et ne doit répondre qu’à un seul acteur.

Question 2

Quelles sont les conséquences à ne pas respecter le SRP?

Code difficile à réutiliser et à comprendre. Maintenance du code plus difficile:

  • Effets d'avalanche possibles
  • Souvent associé à de la duplication avec le temps
  • Difficile à tester
  • Difficulté de travailler en équipe
  • Difficile à débugger
  • Risque élevé d'erreurs et de bogues

Question 3

Trouvez un exemple pour lequel respecter le SRP pourrait rendre le code moins maintenable.

Un exempl parmi tant d'autres serait d'utiliser les méthodes find et create ensemble à plusieurs reprises dans le code au lieu d’utiliser une méthode findOrCreate. Bien que cette dernière ne respecte pas le SRP, si le contexte du client demande à ce que le find et le create soient toujours de pair, les associer ensemble peut aider davantage à la maintenabilité que si elles étaient séparées pour respecter le SRP.

Question 4

Comment faire respecter le SRP par une chaîne de responsabilités? (Ce pattern n'est pas matière au cours, mais voir https://sourcemaking.com/design_patterns/chain_of_responsibility/java/1 pour plus d'explications)

Bien qu’à première vue on puisse penser que le SRP n’est pas respecté, parce qu'il implique plusieurs responsabilités et plusieurs raisons de changer, il en est pourtant le contraire. En effet le pattern de chaîne de responsabilité nécessite une interface générale et chacune de ses implémentations s’occupe de sa propre responsabilité.

Question 5

Que se passe t-il si, dû à une mauvaise compréhension du SRP, on simplifie trop le code au point de créer plusieurs classes qui ne possèdent qu’une seule méthode chacune?

Il y aura plusieurs classes trop simplistes qui devront faire appel les unes aux autres ce qui entraînera plusieurs injections de dépendance et rendra le code difficile à comprendre et à maintenir. Il est important de se rappeler que le but des principes SOLID est entre autres de rendre le code plus maintenable, compréhensible, donc si c’est l’inverse qui se produit, c’est que les principes sont mal appliqués. Dans le cas de la mise en situation, on transforme un problème de cohésion en problème de couplage. L'architecture logicielle vise à balancer ces enjeux.

Question 6

Quel autre principe pourrait être violé lorsque le SRP n’est pas respecté et pourquoi?

Le TDA (Tell don't Ask) et les "god classes" puisqu'elles s'occupent de tout et font donc appel aux informations des autres pour ce faire (getX, getY, etc.).

Question 7

En quoi ceci ne respecte pas le SRP et que feriez-vous pour qu’il soit respecté:


public class PayRollService {
    ...

    public void payEmployee (Employee employee) {
        if (employee.getType() == EmployeeType.PERMANENT ) {
            ...
        } else if (employee.getType() == EmployeeType.CONSULTANT) {
            ...
        }
        paycheck = checkService.issuePaychek(employee);
        this.sendPaycheck(paycheck);
    }
}

Ici il y a deux raisons de changer => lorsque la logique de paiement selon les types d’employé changera et lorsque la logique d’émission/envoi des chèques changera. La classe Employee devrait elle-même gérer la logique qui dépend de son type. La méthode sendPaycheck de la classe pourrait également être déplacée.

Question 8

En quoi ceci ne respecte pas le SRP et que feriez-vous pour qu’il soit respecté:


public class ShoppingCart {

    ...

    public Invoice calculateTotal (List<Product> products) {
        double total = 0;
        for (Product product: products) {
            total += product.getPrice();
        }

        Invoice invoice = new Invoice(total);
        return invoice;
    }
}

S’occupe de créer une facture et s’occupe de calculer le total donc changera si la logique de création d’une facture changera et si la logique de calcul du total changera. Il faudrait déléguer la création de la facture à une autre classe (exemple une factory).