Pattern G.R.A.S.P Forte cohésion

Problème initial

Comment faire pour garder une cohérence d’un système ? Comment s’assurer que les objets d’un système réalisent bien ce qu’ils sont censés réaliser ?

Solution associée

Il faut attribuer une responsabilité à chaque classe de telle sorte à ce que cette responsabilité soit cohérente avec la classe donnée et le système dans sa globalité.

Définition

Qu’est-ce que la cohésion ?

La cohésion mesure la compréhensibilité des classes. Une classe doit avoir des responsabilités cohérentes, et ne doit pas avoir des responsabilités trop variées. Une classe ayant des responsabilités non cohérentes est difficile à comprendre et à maintenir. La forte cohésion favorise :
  • La compréhension de la classe,
  • La maintenance de la classe,
  • La réutilisation des classes ou modules.
Les classes ayant une faible cohésion effectuent des tâches sans liens entre elles ou effectuent trop de tâches

Attention, cela signifie que la mesure de la cohésion ne se fait pas en fonction du nombre de chose que fait une classe mais à la cohérence entre toutes ces choses !

Remarque : la cohésion est fortement liée au couplage ! En effet bien souvent un faible couplage cohérent implique une forte cohésion puisque chaque classe a bien les fonctions qu’elle doit réaliser.

Exemple

On peut reprendre l’exemple donné pour le faible couplage :

Soit les trois classes suivantes avec leurs spécifications :
  • Facture : Contient un ensemble de produit facturé et est associée à un mode de paiement,
  • MoyenDePaiement : Décrit un mode de paiement (espèces, chèque, carte bancaire, à crédit, ...),
  • Client : Paye les factures.
On cherche à ajouter la méthode payer() qui permet de payer une/des facture(s) à l’aide d’un moyen de paiement dont le type est passé en paramètre. Selon le moyen de Paiement on imagine que le total d’une facture change à cause des frais supplémentaires. Deux solutions s’offrent à nous :

1ère solution :



Dans cette première solution, le client, en payant, créé une instance de MoyenDePaiement puis l’assigne à l’objet Facture et enfin réalise le paiement de la dite facture avec le moyen de paiement ajouté.

2ème solution :



Dans cette deuxième solution la méthode payer() délègue l’action de créé une instance de MoyenDePaiement à la classe Facture. Ainsi la classe Client se contente simplement d’appeler la méthode getTotal() qui lui retourne la somme à payer.

Quelle est la meilleure solution et pourquoi ?

C’est la seconde solution car c’est elle qui respecte le mieux le principe de cohésion.
En effet dans la 1ère solution, la classe Client possède trop de responsabilité incohérente : celle de créer une instance de MoyenDePaiement, d’attribuer un moyen de paiement à une facture et celle d’obtenir le total d’une facture pour calculer le montant à payer.

Tandis que dans la 2ème solution la classe Client a d’une part moins de responsabilité mais aussi et surtout des responsabilités cohérentes.
Dans ce cas-là on peut dire que la classe Client a une forte cohésion.

A retenir

Là où le couplage évalue le nombre de relation, de dépendance d’une classe avec une autre, la cohésion évalue la cohérence de la classe en fonction de ce qu’on lui a donné à faire.

Ainsi pour appliquer la forte cohésion il faut se demander :
  • Cette classe réalise-t-elle bien tout ce qu’elle doit réaliser ?
  • N’en fait-elle pas trop ?
  • Ses fonctions sont-elles cohérentes ?
Pour voir si ce principe est bien appliqué à une classe on peut essayer de décrire cette classe en une phrase. Si l’on n’y arrive pas c’est qu’elle n’est pas cohérente et aura donc une faible cohésion.