ConstructiCat Logo
CodeBust.
Browse section ▾

Couplage (programmation informatique).

Degré d'interdépendance entre les modules logiciels

En génie logiciel, le couplage est le degré d'interdépendance entre les modules logiciels, une mesure du degré de connexion entre deux routines ou modules, et de la force des relations entre les modules. Le couplage n'est pas binaire mais multidimensionnel.

Le couplage est généralement opposé à la cohésion. Un faible couplage est souvent corrélé à une forte cohésion, et inversement. Un faible couplage est souvent considéré comme le signe d'un système informatique bien structuré et d'une bonne conception ; combiné à une forte cohésion, il favorise les objectifs généraux d'une grande lisibilité et maintenabilité.

Histoire

Les métriques de qualité logicielle que sont le couplage et la cohésion ont été inventées par Larry Constantine à la fin des années 1960 dans le cadre de la conception structurée, à partir des caractéristiques des « bonnes » pratiques de programmation qui réduisaient les coûts de maintenance et de modification. La conception structurée, y compris la cohésion et le couplage, a été présentée dans l'article Stevens, Myers & Constantine (1974) et le livre Yourdon & Constantine (1979), ce dernier établissant par la suite ces termes comme standards.

Couplage et cohésion

Le couplage et la cohésion sont des termes qui apparaissent très souvent ensemble. Le couplage désigne les interdépendances entre les modules, tandis que la cohésion décrit le degré de parenté des fonctions au sein d'un même module. Une faible cohésion signifie qu'un module donné effectue des tâches peu liées les unes aux autres et peut donc engendrer des problèmes à mesure que le module grossit.

Degré

Le couplage peut être « faible » (aussi qualifié de « lâche » ou « ténu ») ou « élevé » (aussi qualifié de « serré » ou « fort »). Voici certains types de couplage, du couplage le plus élevé au plus faible :

Programmation procédurale

Un module désigne ici un sous-programme de quelque nature que ce soit, c'est-à-dire un ensemble d'une ou plusieurs instructions ayant un nom et, de préférence, son propre jeu de noms de variables.

Couplage de contenu (élevé)
On parle de couplage de contenu lorsqu'un module utilise le code d'un autre module, par exemple un branchement. Cela viole le masquage de l'information, un concept fondamental de la conception logicielle.
Couplage commun
On parle de couplage commun lorsque plusieurs modules ont accès aux mêmes données globales. Mais cela peut entraîner une propagation incontrôlée des erreurs et des effets de bord imprévus lors des modifications.
Couplage externe
Le couplage externe se produit lorsque deux modules partagent un format de données imposé de l'extérieur, un protocole de communication ou une interface de périphérique. Cela concerne essentiellement la communication avec des outils et des périphériques externes.
Couplage de contrôle
Le couplage de contrôle correspond à un module qui contrôle le déroulement d'un autre en lui transmettant des informations sur ce qu'il doit faire (par exemple, en passant un indicateur d'action à exécuter).
Couplage par structure (couplage par données structurées)
Le couplage par structure se produit lorsque des modules partagent une structure de données composite et n'en utilisent que certaines parties, éventuellement différentes (par exemple, en passant un enregistrement complet à une fonction qui n'a besoin que d'un seul de ses champs).
Dans cette situation, la modification d'un champ dont un module n'a pas besoin peut conduire à changer la manière dont ce module lit l'enregistrement. Pour illustrer le concept de couplage par structure, prenons l'exemple d'un composant UserProfile. Ce composant est conçu pour renvoyer l'intégralité des informations du profil utilisateur en réponse aux requêtes, même lorsque les consommateurs n'ont besoin que d'un attribut particulier. Cette pratique illustre le couplage par structure, qui peut engendrer d'importants problèmes de bande passante, en particulier à grande échelle. Lorsqu'un attribut quelconque du composant UserProfile change, tous les consommateurs qui interagissent avec lui peuvent devoir faire l'objet de tests, même s'ils n'utilisent pas l'attribut modifié.
Couplage de données
Le couplage de données se produit lorsque des modules partagent des données, par exemple via des paramètres. Chaque donnée est un élément élémentaire, et ce sont les seules données partagées (par exemple, en passant un entier à une fonction qui calcule une racine carrée).

Programmation orientée objet

Couplage de sous-classe
Décrit la relation entre un enfant et son parent. L'enfant est lié à son parent, mais le parent n'est pas lié à l'enfant.
Couplage temporel
C'est le fait de regrouper deux actions dans un même module uniquement parce qu'elles se produisent en même temps.

Des travaux récents ont étudié divers autres concepts de couplage et les ont utilisés comme indicateurs de différents principes de modularisation appliqués en pratique.

Couplage dynamique

L'objectif de la définition et de la mesure de ce type de couplage est de fournir une évaluation à l'exécution d'un système logiciel. On a fait valoir que les métriques de couplage statique perdent en précision lorsqu'on a affaire à un usage intensif de la liaison dynamique ou de l'héritage. Pour tenter de résoudre ce problème, des mesures de couplage dynamique ont été prises en compte.

Couplage sémantique

Ce type de métrique de couplage prend en compte les similitudes conceptuelles entre entités logicielles en utilisant, par exemple, les commentaires et les identifiants, et en s'appuyant sur des techniques telles que l'indexation sémantique latente (LSI).

Couplage logique

L'analyse du couplage logique (ou couplage évolutif, ou couplage de changement) exploite l'historique des versions d'un système logiciel pour repérer des schémas de changement parmi les modules ou les classes : par exemple, des entités susceptibles d'être modifiées ensemble ou des séquences de modifications (une modification dans une classe A est toujours suivie d'une modification dans une classe B).

Dimensions du couplage

Selon Gregor Hohpe, le couplage est multidimensionnel :

  • Dépendance technologique
  • Dépendance de localisation
  • Dépendance topologique
  • Dépendance au format et au type de données
  • Dépendance sémantique
  • Dépendance conversationnelle
  • Dépendance d'ordre
  • Dépendance temporelle

Inconvénients du couplage fort

Les systèmes fortement couplés présentent généralement les caractéristiques de développement suivantes, souvent considérées comme des inconvénients :

  1. Une modification dans un module entraîne généralement un effet de cascade de modifications dans d'autres modules.
  2. L'assemblage des modules peut exiger plus d'efforts et/ou de temps en raison de l'interdépendance accrue entre modules.
  3. Un module donné peut être plus difficile à réutiliser et/ou à tester, car les modules dont il dépend doivent être inclus.

Problèmes de performance

Qu'il soit faiblement ou fortement couplé, les performances d'un système sont souvent réduites par la création, la transmission, la traduction (par exemple le marshaling) des messages et des paramètres, ainsi que par l'interprétation des messages (qui peut être une référence à une chaîne, à un tableau ou à une structure de données), ce qui nécessite moins de surcharge que la création d'un message complexe tel qu'un message SOAP. Les messages plus longs nécessitent davantage de CPU et de mémoire pour être produits. Pour optimiser les performances à l'exécution, il faut minimiser la longueur des messages et maximiser leur signification.

Surcharge de transmission des messages et performance
Comme un message doit être transmis intégralement pour conserver tout son sens, sa transmission doit être optimisée. Les messages plus longs nécessitent davantage de CPU et de mémoire pour être transmis et reçus. De plus, le cas échéant, les destinataires doivent réassembler un message dans son état d'origine pour le recevoir complètement. Par conséquent, pour optimiser les performances à l'exécution, il faut minimiser la longueur des messages et maximiser leur signification.
Surcharge de traduction des messages et performance
Les protocoles de messages et les messages eux-mêmes contiennent souvent des informations supplémentaires (c'est-à-dire des informations de paquet, de structure, de définition et de langage). Le destinataire doit donc souvent traduire un message dans une forme plus épurée en supprimant les caractères et les informations de structure superflus et/ou en convertissant des valeurs d'un type à un autre. Toute forme de traduction augmente la surcharge de CPU et/ou de mémoire. Pour optimiser les performances à l'exécution, la forme et le contenu des messages doivent être réduits et affinés afin de maximiser leur signification et de réduire la traduction.
Surcharge d'interprétation des messages et performance
Tous les messages doivent être interprétés par le destinataire. Les messages simples tels que les entiers peuvent ne nécessiter aucun traitement supplémentaire pour être interprétés. En revanche, les messages complexes tels que les messages SOAP nécessitent un analyseur syntaxique et un transformateur de chaînes pour exprimer le sens voulu. Pour optimiser les performances à l'exécution, les messages doivent être affinés et réduits afin de minimiser la surcharge d'interprétation.

Solutions

Une approche pour réduire le couplage est la conception fonctionnelle, qui cherche à limiter les responsabilités des modules selon les fonctionnalités. Le couplage augmente entre deux classes A et B si :

  • A possède un attribut qui référence (est de type) B.
  • A fait appel aux services d'un objet B.
  • A possède une méthode qui référence B (via le type de retour ou un paramètre).
  • A est une sous-classe de (ou implémente) la classe B.

Un faible couplage désigne une relation dans laquelle un module interagit avec un autre module via une interface simple et stable, sans avoir à se préoccuper de l'implémentation interne de l'autre module (voir masquage de l'information).

Des systèmes tels que CORBA ou COM permettent aux objets de communiquer entre eux sans avoir à connaître quoi que ce soit de l'implémentation de l'autre objet. Ces deux systèmes permettent même à des objets de communiquer avec des objets écrits dans d'autres langages.

Couplage et connascence

Le couplage décrit le degré et la nature de la dépendance entre composants logiciels, en se concentrant sur ce qu'ils partagent (par exemple, des données, un flux de contrôle, une technologie) et sur l'étroitesse de leur lien. Il évalue deux dimensions clés : la force, qui mesure la difficulté à modifier la dépendance, et la portée (ou visibilité), qui indique l'ampleur de l'exposition de la dépendance à travers les modules ou les frontières. Les types de couplage traditionnels comprennent généralement le couplage de contenu, le couplage commun, le couplage de contrôle, le couplage par structure, le couplage externe et le couplage de données.

La connascence, introduite par Meilir Page-Jones, fournit un cadre systématique pour analyser et mesurer les dépendances de couplage. Elle évalue les dépendances selon trois dimensions : la force, qui mesure l'effort nécessaire pour refactoriser ou modifier la dépendance ; la localité, qui considère la proximité physique ou logique des composants dépendants au sein du code source ; et le degré, qui mesure le nombre de composants affectés par la dépendance. La connascence peut être classée en formes statique (détectable à la compilation) et dynamique (détectable à l'exécution). La connascence statique désigne les dépendances à la compilation, telles que les signatures de méthodes, tandis que la connascence dynamique désigne les dépendances à l'exécution, qui peuvent se manifester sous des formes telles que la connascence de temporalité, de valeurs ou d'algorithme.

Chaque variante de couplage peut présenter plusieurs types de connascence, un type précis ou, dans de rares cas, aucun, selon la manière dont la dépendance est implémentée. Les types courants de connascence comprennent la connascence de nom, de type, de position et de signification. Certains types de couplage s'accordent naturellement avec des types de connascence spécifiques ; par exemple, le couplage de données implique souvent une connascence de nom ou de type. Toutefois, toutes les combinaisons de couplage et de connascence n'ont pas un sens pratique. Les dépendances reposant sur l'ordre des paramètres dans une signature de méthode présentent une connascence de position, fragile et difficile à refactoriser, car réordonner les paramètres rompt l'interface. À l'inverse, la connascence de nom, qui repose sur les noms des champs ou des paramètres, est généralement plus résistante au changement. Les types de connascence présentent eux-mêmes une hiérarchie naturelle de force, la connascence de nom étant généralement considérée comme plus faible que la connascence de signification.

Les dépendances qui traversent les frontières des modules ou des systèmes distribués entraînent généralement des coûts de coordination plus élevés, ce qui accroît la difficulté de refactoriser et de propager les changements au-delà de frontières lointaines. Des pratiques modernes, telles que l'injection de dépendances et la programmation fondée sur des interfaces, sont souvent employées pour réduire la force du couplage et améliorer la maintenabilité des dépendances.

Alors que le couplage identifie ce qui est partagé entre les composants, la connascence évalue le comportement de ces dépendances, la manière dont les changements se propagent et la difficulté à les refactoriser. La force, la localité et le degré sont interdépendants ; les dépendances dotées d'une grande force, d'une large portée et traversant des frontières lointaines sont nettement plus difficiles à refactoriser et à maintenir. Ensemble, le couplage offre une vue d'ensemble des relations de dépendance, tandis que la connascence fournit un cadre granulaire pour analyser la force, la localité, le degré et la résilience au changement des dépendances, soutenant la conception de systèmes maintenables et robustes.

Couplage de module

Le couplage en génie logiciel décrit une version des métriques associées à ce concept.

Pour le couplage de flux de données et de contrôle :

  • : nombre de paramètres de données en entrée
  • : nombre de paramètres de contrôle en entrée
  • : nombre de paramètres de données en sortie
  • : nombre de paramètres de contrôle en sortie

Pour le couplage global :

  • : nombre de variables globales utilisées comme données
  • : nombre de variables globales utilisées comme contrôle

Pour le couplage environnemental :

  • : nombre de modules appelés (fan-out)
  • : nombre de modules appelant le module considéré (fan-in)

Coupling(C) donne une valeur d'autant plus grande que le module est couplé. Ce nombre varie d'environ 0,67 (faible couplage) à 1,0 (fortement couplé)

Par exemple, si un module ne possède qu'un seul paramètre de données en entrée et en sortie

Si un module possède 5 paramètres de données en entrée et en sortie, un nombre égal de paramètres de contrôle, et accède à 10 éléments de données globales, avec un fan-in de 3 et un fan-out de 4,