Les 4 niveaux de maturité du découplage

Récemment,  j’écoutais un podcast de Benoit Gantaume (par exemple l’épisode https://podcast.ausha.co/artisan-developpeur/77-commencer-le-tdd-sur-du-code-legacy-avec-xavier-nopre), il y faisait part, entre autres, d’un des problèmes les plus sérieux en termes de développement : le couplage. A cette occasion je réalisais après toutes ces années, que j’avais fini moi aussi par considérer le couplage comme le problème numéro un du code.

Avant tout, qu’est-ce que le couplage ?

Bien sûr on peut trouver des définitions formelles (https://en.wikipedia.org/wiki/Coupling_(computer_programming)). Mais j’aimerais proposer ici une définition plus simple et plus large : selon moi, le couplage transparaît lorsque au moins deux sujets se retrouvent liés l’un à l’autre de façon non maitrisée. Cette définition me permet d’appréhender des problèmes techniques, oui, mais pas seulement.

Avec ma définition, le couplage est protéiforme, il peut être technique ou fonctionnel, humain, organisationnel, microscopique ou macroscopique, explicite ou caché. Pour donner quelques exemples qui expriment cette diversité :
– la façon dont un PO expose ses besoins oriente les choix techniques
– la documentation word/excel dissociée du code effectif
– la documentation dans les fichiers de code
– les copier/coller (même intention à différents endroits du code)
– l’héritage
– le « spécialiste » (c’est LA personne qui connaît LE sujet)
– les effets de bords
– les composants « génériques »
– les applications qui ne peuvent être lancées de façon autonome
– les pseudos tests unitaires
– l’UI mélangée au métier
– les adhérences entre couches logicielles
– les adhérences entre équipes
– les adhérences entre projets
– les adhérences organisationnelles (des équipes agiles dans un cycle en V par exemple)
– …

Certains éléments de cette liste peuvent paraître étranges, j’y reviendrais certainement plus en détail dans un autre article. La liste n’est évidemment pas exhaustive, notons au passage que les éléments de cette liste y évoluent selon plusieurs axes :
– la granularité (de la simple ligne de code au SI)
– un axe fonctionnel <-> technique
– la force avec laquelle ce couplage s’exprime
– l’expressivité du couplage (visible-explicite / invisible-implicite)

Niveaux de maturité face au couplage 

A cette notion de couplage vient se greffer la perception des personnes qui y sont confrontées.
On peut arbitrairement déclarer plusieurs niveaux de maturité face à ce sujet:
– conscience du problème
– intérêt porté au problème
– compétence de « reconnaissance » (savoir détecter un couplage)
– compétence de découplage (savoir-faire)

« Si vous êtes à la fois ignorant de l’ennemi et de vous-même, vous êtes sûrs de vous trouver en péril à chaque bataille » Sun Tzu – L’art de la guerre – 2008 – Flammarion.

J’imagine que les développeurs suffisamment expérimentés seront arrivés à une conclusion similaire : le couplage est le problème numéro un du code. Mais comment parvenir à cette conclusion ? Comment combattre un ennemi que l’on ignore ? Je vous propose un petit parcours initiatique express qui vous permettra de mieux le connaître.

Avez-vous déjà souffert des problèmes suivants ? 

– j’ai du mal à tester mon code sans remonter tout le SI
– je suis trop dépendant d’autres couches (ex je réalise l’interface d’un composant, mais j’ai besoin du
« back » java, de mainframes, de bases de données)
– ma couverture de code n’est pas satisfaisante
– je suis obligé de lancer l’application pour tester
– je suis obligé de modifier mon modèle métier alors que c’est l’affichage qui change
– je suis obligé de modifier beaucoup de code pour chaque modification minime
– j’ai du mal à réutiliser les composants « communs » ou « génériques », je dois introduire du code
spécifique pour les faire fonctionner, je « casse » les autres applications quand je le fais évoluer
– j’ai de la peine à prendre en compte les ajustements / évolutions métier sans tout remettre en cause
– le feed back de mes tests est trop lent.
Pour toutes ces raisons, je n’avance pas aussi vite que j’aimerais.

Si vous avez été confronté à ce genre de problèmes, c’est que vraisemblablement vous avez du couplage dans votre projet, et non, un coup de « calgon » ne réglera pas votre problème.
Cette liste de désagréments n’est, là aussi, pas exhaustive. Ce genre de difficultés est souvent associé au « big ball of mud », au plat de spaghetti, et ce n’est pas un hasard, ce sont des expressions imagées qui traduisent l’enchevêtrement, l’intrication de différentes parties du code.
Ce genre de problèmes peut conduire à :
– un ralentissement du projet
– une maintenance de plus en plus difficile
– une explosion des coûts
…Et finalement un abandon pur et simple du projet.

Prendre conscience du problème

Si vous vous retrouvez dans ces situations, alors vous avez d’ores et déjà franchi une première étape : la prise de conscience du problème.

S’intéresser au problème

La deuxième étape, l’intérêt à porter au découplage, est assez simple : il faut avoir souffert, ou faire confiance aux personnes qui ont déjà souffert avant vous. Si vous n’avez pas assez souffert, il est possible que vous restiez bloqués à ce niveau, et la motivation pour franchir les étapes suivantes risque de ne pas être au rendez-vous. Je pense finalement que c’est une façon de départager les développeurs expérimentés des autres, au-delà du fait que certains auront éprouvé différentes choses, les autres auront été éprouvés par différents projets.
Mais en étant optimiste, peut-être que la soif de connaissance peut être suffisante pour passer cette étape.

Savoir détecter un couplage

La troisième étape, savoir détecter un couplage, n’est pas forcément facile. Cela dépend de deux choses : l’œil du développeur et l’expressivité du couplage. Plus le couplage sera implicite, plus l’œil du développeur devra être aiguisé.
Par exemple, il est assez simple de détecter qu’une fonction typescript dépend du contexte. On peut notamment rechercher les « this », on pourra aussi jeter un coup d’œil à sa signature : une fonction qui ne prend aucun argument et n’en retourne aucun est pour le moins suspicieuse. Ça sent l’effet de bord à plein nez. Qui dit effet de bord dit couplage au contexte. Ici le couplage se détecte en un coup d’œil. On recherche localement à la fonction des mots clefs.
Là où les choses se compliquent, c’est lorsque le couplage est « distant ». Deux parties du code qui auraient dû être utilisées conjointement ont été arbitrairement dissociées. C’est à mon sens la caractéristique la plus vicieuse qu’on puisse trouver dans le code : prises indépendamment, deux parties semblent dissociées mais sont en fait étroitement liées.

Ici les parties A et B du code ont été arbitrairement séparées par un développeur, on perd l’intention finale du code (ici voir un disque jaune).

En décidant de ne pas spécialiser un comportement, on a couplé deux parties de code qui ont été découpées l’une de l’autre. Découper n’est pas découpler. Il y aurait encore beaucoup de choses à dire sur cette troisième étape, mais on peut déjà en retenir que l’expérience du développeur va là aussi beaucoup jouer.

Comment découpler

Dernière étape, comment découpler : les remèdes. Il y a bien des façons d’éviter le piège du couplage :
– pratique du TDD (Test Driven Developpement)
– pratique du DDD (Domain Driven Design)
– pratique de l’architecture hexagonale
– pratique des principes SOLID (en particulier SRP – Single Responsability Principle -, ISP – Interface
Segregation Principle – et DIP – Dependency Inversion Principle -)
– pair programming
Et j’en passe.
Sans surprise on retrouve des principes software craftsmanship.
Souvent ces sujets sont malheureusement envisagés indépendamment les uns des autres, mais ils forment en fait un ensemble cohérent, une espèce d’écosystème sur lequel repose effectivement le software craftsmanship.

Cette dernière étape fera elle aussi partie d’une suite d’articles consacrés au découplage.

Romain,
Software Craftsman Fullstack Dev.