6  Principes GRASP

GRASP est un acronyme de l’expression anglaise « General Responsibility Assignment Software Patterns », c’est-à-dire les principes pour affecter les responsabilités logicielles dans les classes.

Une approche GRASP devrait amener un design vers la modularité et la maintenabilité.

L’acronyme d’une expression vulgarisée pourrait être POMM : « Principes pour déterminer Où Mettre une Méthode. »

En tant qu’ingénieur(e) logiciel, vous devez décider souvent où placer une méthode (dans quelle classe), et cette décision ne devrait pas être prise de manière arbitraire, mais plutôt en suivant les directives d’ingénierie favorisant la modularité.

Alors, les GRASP sont les directives qui vous aident à prendre des décisions de conception, menant à un design avec moins de couplage inutile et avec des classes plus cohésives. Les classes cohésives sont plus faciles à comprendre, à maintenir et à réutiliser.

 Avez-vous déjà une bonne expérience en programmation ? Avez-vous l’habitude de coder rapidement des solutions qui fonctionnent ? Si la réponse est oui, alors travailler avec les principes GRASP peut être un défi pour vous. Dans la méthodologie enseignée dans ce manuel, vous devez être en mesure de justifier vos choix de conception, et cela va vous ralentir au début (réflexe du « hacking cowboy » peut-être?). Le but avec les principes GRASP est de (ré)apprendre à faire du code qui fonctionne, mais qui est également facile à maintenir. C’est normal au début que ça prenne plus de temps, car il faut réfléchir pour appliquer les principes. Une fois que vous aurez l’habitude d’utiliser les GRASP, vous serez encore rapide avec votre développement, mais, en plus, votre design sera meilleur sur le plan de la maintenabilité, et vous aurez plus de confiance dans vos choix.

6.1 Spectre de la conception

Neal Ford (2009) a proposé la notion d’effort pour la conception qu’il a nommée le « Spectre de la conception ». La figure 6.1 illustre le principe.

]« Cascade pure »+Beaucoup deconceptionau début(BDUF)+Un peu de designau début(Some DUF)+AgileDesignémergent[« Hacking cowboy »

Figure 6.1: Spectre de la conception, adapté de Ford (2009). (PlantUML)

À une extrémité, il y a la mentalité de mettre presque zéro effort pour une conception, que l’on nomme « Hacking Cowboy ». C’est le cas lors d’un hackathon (un marathon de programmation durant 24 ou 48 heures où il faut produire une solution rapidement). Vous ne feriez pas un logiciel avec 10 patrons GoF ou les diagrammes UML pour réfléchir à votre architecture. Mais vous savez aussi que le code qui est produit lors d’un hackathon ne sera pas facile à maintenir. Le seul but est de faire du code qui marche pour montrer une idée intéressante.

Au fait, dans certains contextes d’entreprise (par exemple une entreprise en démarrage qui a seulement six mois de financement), c’est une situation similaire. Si une solution de « produit minimum viable » (MVP en anglais)  n’existe pas à la fin de la période de financement, l’entreprise n’existera plus, car il n’y aura pas une seconde période de financement. Si l’entreprise est financée pour une seconde période, la conception du code pourrait avoir besoin de beaucoup de soin, car elle a aura été négligée. Cette négligence à la conception (pour la maintenabilité) est aussi nommée la dette technique.

À l’autre extrémité du spectre, c’est beaucoup d’effort dépensé sur la conception, que l’on nomme « Cascade pure ». Dans le cycle de vie en cascade, on met un temps fixe, par exemple plusieurs mois, à étudier la conception. Comme toute chose poussée à l’extrême, ce n’est pas idéal non plus. Dans son livre, Larman (2005) explique en détail des problèmes posés par une approche en cascade. Dans certains domaines, par exemple les logiciels pour le contrôle d’avions ou d’appareils médicaux, une approche en cascade est encore utilisée, en dépit des problèmes dus à l’approche. La sécurité et la robustesse des logiciels sont très importantes, alors on passe beaucoup de temps à vérifier et à valider la conception. Puisque les exigences sont plus stables (et les développeurs(euses) ont a priori une meilleure compréhension du domaine), l’approche en cascade n’est pas si mal. Pourtant, le coût pour produire des logiciels certifiés est énorme.

Le spectre de la conception est très important pour le monde réel, parce qu’une ingénieure ou un ingénieur devrait pouvoir s’adapter selon les attentes de son travail. Le dogme sur « la bonne manière » de développer un logiciel est souvent sans contexte. C’est le contexte de l’entreprise pour laquelle vous travaillez qui peut déterminer combien d’effort à mettre sur la conception. Cependant, méfiez-vous des entreprises qui ne portent aucune attention à la conception (l’extrémité « hacking cowboy » du spectre), même si l’on vous dit que c’est « agile ».

6.2 Tableau des principes GRASP

Voici un extrait du livre de Larman (2005).

Tableau 6.1: Patterns (principes) GRASP
Pattern Description
Expert en information
F16.11/A17.11
Un principe général de conception d’objets et d’affectation des responsabilités. Affectez une responsabilité à l’expert – la classe qui possède les informations nécessaires pour s’en acquitter.
Créateur
F16.10/A17.10
Qui crée ? (Notez que Fabrique Concrète est une solution de rechange courante.) Affectez à la classe B la responsabilité de créer une instance de la classe A si l’une des assertions suivantes est vraie :
  1. B contient A
 2. B agrège A
 3. B a les données pour initialiser A
 4. B enregistre A
 5. B utilise étroitement A
Contrôleur
F16.13/A17.13
Quel est le premier objet en dehors de la couche présentation qui reçoit et coordonne (« contrôle ») les opérations système ?

Affectez une responsabilité à la classe qui correspond à l’une de ces définitions :
 1. Elle représente le système global, un « objet racine », un équipement ou un sous-système (contrôleur de façade).
 2. Elle représente un scénario de cas d’utilisation dans lequel l’opération système se produit (contrôleur de session ou contrôleur de cas d’utilisation). On la nomme GestionnaireX, où X est le nom du cas d’utilisation.
Faible Couplage
(évaluation)
F16.12/A17.12
Comment minimiser les dépendances ?

Affectez les responsabilités de sorte que le couplage (inutile) demeure faible. Employez ce principe pour évaluer les alternatives.
Forte Cohésion
(évaluation)
F16.14/A17.14
Comment conserver les objets cohésifs, compréhensibles, gérables et, en conséquence, obtenir un Faible Couplage ?

Affectez les responsabilités de sorte que les classes demeurent cohésives. Employez ce principe pour évaluer les différentes solutions.
Polymorphisme
F22.1/A25.1
Qui est responsable quand le comportement varie selon le type ?

Lorsqu’un comportement varie selon le type (classe), affectez la responsabilité de ce comportement – avec des opérations polymorphes – aux types selon lesquels le comportement varie.
Fabrication Pure
F22.2/A25.2
En cas de situation désespérée, que faire quand vous ne voulez pas transgresser les principes de faible couplage et de forte cohésion ?

Affectez un ensemble très cohésif de responsabilités à une classe « comportementale » artificielle qui ne représente pas un concept du domaine — une entité fabriquée pour augmenter la cohésion, diminuer le couplage et faciliter la réutilisation.
Indirection
F22.3/A25.3
Comment affecter les responsabilités pour éviter le couplage direct ?

Affectez la responsabilité à un objet qui sert d’intermédiaire avec les autres composants ou services.
Protection des variations
F22.4/A25.4
Comment affecter les responsabilités aux objets, sous-systèmes et systèmes de sorte que les variations ou l’instabilité de ces éléments n’aient pas d’impact négatif sur les autres ?

Identifiez les points de variation ou d’instabilité prévisibles et affectez les responsabilités afin de créer une « interface » stable autour d’eux.

6.3 GRASP et RDCU

Les principes GRASP sont utilisés dans les réalisations de cas d’utilisation (RDCU). On s’en sert pour annoter les décisions de conception, pour rendre explicites (documenter) les choix. Voir la section Réalisations de cas d’utilisation (RDCU) pour plus d’informations.

6.4 GRASP et patterns GoF

On peut voir les principes GRASP comme des généralisations (principes de base) des patterns GoF. Voir la section Décortiquer les patterns GoF avec GRASP pour plus d’informations.

6.5 Exercices

Exercice 6.1 (GRASP Polymorphisme) Soit le diagramme de classe modélisant l’exemple de Fowler (2018) à Replace Conditional with Polymorphism :

Birdtype : StringnumberOfCoconuts : numbervoltage : numbergetPlumage() : String

Appliquez GRASP Polymorphisme pour le code suivant :

get plumage() {
    switch (this.type) {
        case 'EuropeanSwallow':
            return "average";
        
        case 'AfricanSwallow':
            return (this.numberOfCoconuts > 2) ? "tired" : "average";
        
        case 'NorwegianBlueParrot':
            return (this.voltage > 100) ? "scorched" : "beautiful";
        
        default:
            return "unknown";
    }
}

Exercice 6.2 (GRASP Cohésion) Il est tiré du livre de (freeman_head_2021?).

  • Lesquelles des classes suivantes ont de multiples responsabilités ?

Jeulogin()inscrire()déplacer()tirer()rester()JoueursetNom()setAdresse()setNuméroTéléphone()sauvegarder()charger()Téléphonecomposer()raccrocher()parler()envoyerDonnées()flash()JeuCarteshasNext()next()remove()addCard()removeCard()shuffle()Panierajouter()enlever()encaisser()sauvegarder()IteratorhasNext()next()remove()

  • Déterminez si ces classes ont une cohésion forte ou faible :

Jeulogin()inscrire()déplacer()tirer()rester()getMeilleureScore()getNom()SessionPartielogin()inscrire()ActionsJoueurdéplacer()tirer()rester()JoueurgetMeilleurScore()getNom()

Exercice 6.3 (GRASP Contrôleur)  

  • Expliquez pourquoi le principe du GRASP Contrôleur (lorsqu’il s’agit d’un contrôleur de session ou de cas d’utilisation) est une Fabrication Pure.

  • Soit un contrôleur de session GestionnaireVentes, quelle est la « situation désespérée » que résout cette Fabrication pure ?