Java : Perdre en couplage

Aujourd’hui je vais essayer de vous faire comprendre ce qu’est le couplage (faible ou fort) et pourquoi il faut plutôt s’orienter vers un faible. Je vous donnerai des exemples réalisés en Java sous JDeveloper mais le concept est tout à fait applicables à n’importe que langage orienté objet (c++, c#, PHP, etc.).
Ce concept nous aidera à réaliser des programmes robustes et les rendra tout à fait apte à n’importe quelle évolution. Vous gagnerez aussi en rigueur quant à la conception.

Exemple de couplage trop fort (ou trop serré)

En programmation, lorsqu’on entend parler de couplage serré, il s’agit de plusieurs classes qui sont étroitement connectées les unes aux autres. C’est à dire qu’elles utilises « trop » l’intérieur d’une autre classe. Regardons plutôt un exemple.
Imaginons une application qui doit poser des verrous en fonction des actions faites par l’utilisateur.
On va dire que dès que l’utilisateur veut modifier un élément cela verrouille le reste de l’application. Nous allons donc pour ça, créer une classe que nous allons appeler Application, elle aura pour rôle de centraliser toutes les infos concernant l’application :

  • Le nom de l’utilisateur connecté
  • La liste des actions faites depuis la connexion
  • etc.
  • Et un booléen « locked » qui nous permettra de définir si l’application est verrouillée
class Application {
  public boolean locked;
  private static Application instance = null;
  static {
    instance = new Application();
  }
  private Application() {}
  public Application getInstance() {
    return instance;
  }
}

Maintenant imaginons une classe ProductsList qui sera le contrôleur d’une liste de produits.
Lorsque l’utilisateur connecté entrera en édition sur un des produits, on voudrait que ça verrouille tout le reste de l’application. Et comme nous ne sommes pas très bons développeurs (et surtout parce que nous ne connaissons pas encore ce qu’est le couplage) nous allons créer la classe ProductsList comme décrit ci-dessous.

class ProductsList{
  public ProductsList() {}
  public void startEditProduct(Product product) {
    Application.getInstance().verrou = true;
    /* Reste de la méthode */
  }
  public void stopEditProduct(Product product) {
    Application.getInstance().verrou = false;
    /* Reste de la méthode  */
  }
}

Vous allez me dire que tout va bien, et je suis d’accord. Seulement voilà, votre chef vient vous voir et vous dit qu’il faut aussi mettre des verrous lorsqu’on édité une catégorie de Produits (la classe CategoriesList) et qu’une fois l’utilisateur en édition sur une catégorie, il doit ensuite pouvoir rentrer en édition sur un des produits de cette catégorie.
Voilà ci-dessous comment va fonctionner notre application :

Vous vous rendez bien compte, à l’endroit où est indiqué le Problème, le verrou est ouvert alors qu’il devrait encore être fermé.

Solution du couplage faible (ou lâche)

Voilà maintenant comment aurait été le code si nous avions opté pour un couplage faible.
Application :

class Application {
  private boolean locked;
  private static Application instance = null;
  static {
    instance = new Application();
  }
  private Application() {}
  public static Application getInstance() {
    return instance;
  }
  public void lock() {
    locked = true;
  }
  public void unlock() {
    locked = false;
  }
  public boolean isLocked() {
    return locked;
  }
}

ProductsList :

class ProductsList{
  public ProductsList() {}
  public void startEditProduct(Product product) {
    Application.getInstance().lock();
    /* Reste de la méthode */
  }
  public void stopEditProduct(Product product) {
    Application.getInstance().unlock();
    /* Reste de la méthode  */
  }
}

CategoriesList :
Même modifications que pour ProductsList.
Vous allez me dire que le problème reste le même . Je vous dirai bien oui … mais non.
Reprenons le premier cas (couplage fort) pour corriger le problème vous auriez du reprendre toutes les classes qui nécessitaient l’utilisation du verrou (dans notre cas 2, mais imaginez une application de 50 classes…). Alors que dans le second cas, toute la gestion du verrou se situe dans les méthodes lock() et unlock().
Nous n’avons plus qu’à toucher à la classe Application pour résoudre notre problème :

  • Le verrou va devenir un nombre entier pour gérer le cumul de verrous
  • La méthode lock() va incrémenter le verrou
  • La méthode unlock() va le décrémenter

Application :

class Application {
  private int locked = 0;
  private static Application instance = null;
  static {
    instance = new Application();
  }
  private Application() {}
  public static Application getInstance() {
    return instance;
  }
  public void lock() {
    locked++;
  }
  public void unlock() {
    locked--;
  }
  public boolean isLocked() {
    return locked > 0;
  }
}

ProductsList :
Aucun changement pour celle-ci puisque toute la gestion a été centralisée dans la classe Application.
CategoriesList :
Même remarque que pour ProductsList : aucun changement.

Conclusion

On se rend très rapidement compte du temps perdu à faire la modification si on part d’un couplage fort. Alors qu’en perdant à peine de temps à mettre en place en couplage plus faible (ou plus étroit) on arrive à gagner un maximum de temps derrière.
Je rajouterai pour finir qu’on évite aussi, grâce à cette solution, les erreurs lors de la reprise du code.

2 réflexions sur “Java : Perdre en couplage”

    1. Bonjour,
      Il faut bien sûr privilégier le couplage faible tant que possible. Seulement, il arrive qu’un couplage fort soit imposé par un projet ou par un de ses composants.

Les commentaires sont fermés.