• Aucun résultat trouvé

La restructuration pour factoriser des codes similaires

Elle est utile notamment pour factoriser les codes dupliqués ou similaires. Les codes similaires45 sont une des plaies des applications en maintenance car ils sont le résultat d’un effet de type « copier-coller » où, pour des raisons de rapidité, les mainteniciens reproduisent quasiment à l’identique un bout de code existant pour corriger un « bogue » ou introduire une évolution.

Au lieu de produire un code réutilisable à travers la factorisation d’une fonction, la copie de code produit plus de risques d’erreurs et d’incohérences (une personne qui corrige le code à un endroit ne pensera pas forcément à répliquer la modification dans toutes les copies). Les estimations classiques vont de 8 % à 10 % de codes similaires dans un code normalement industrialisé, mais suivant la longévité de l’application, le pourcentage peut augmenter sensiblement.

Le principe pour factoriser les codes similaires est d’utiliser un outil d’analyse statique de code en support de diagnostic de détection de clones, puis de remplacer les codes similaires par un appel à une fonction réutilisable.

Pour élargir l’efficacité de la détection, on préférera opérer au niveau de la représentation logique. Quand un code est parsé et restitué sous forme d’arbre abstrait syntaxique, on peut calculer des tuples46 de métriques pour chaque sous-arborescence (c’est-à-dire les fonctions) et procéder à une comparaison des arbres/tuples ainsi obtenus pour identifier les similarités.

45 Par définition, les codes similaires sont des segments de code que l’on retrouve à plusieurs endroits d’un système ou dans des fichiers différents, ou encore dans le même fichier mais dans des fonctions différentes, voire dans la même fonction

46En mathématiques, un tuple est une séquence de valeurs (aussi connue en tant que liste ordonnée) appelées composants du tuple. Un tuple est un n-uplet (paire, triplet, quadruplet…). En programmation, un tuple est une donnée objet contenant d’autres objets en éléments, éventuellement de types différents. En SQL, un tuple est une ligne de table (ex : nom, prénom, âge…).

Cette approche, si elle peut être en grande partie automatisable dans la méthode de détection et, une fois les codes isolés, dans la factorisation, nécessite toutefois une vérification humaine et donc des étapes d’interactivité.

Les opérations de refactoring doivent pouvoir s’inscrire dans des cycles de tests de non-régression pour la fluidité du processus.

La modularisation

Quand les sociétés ou organismes utilisent d’énormes programmes qui sont monolithiques, ils subissent les conséquences de la complexité et notamment la lourdeur de la maintenance. En effet, on ne peut pas paralléliser les équipes et les évolutions sont difficiles. Car un simple changement peut nécessiter d’être répliqué dans de multiples parties du code faute d’une modularisation des fonctions.

Définition

Des modules solidaires mais solitaires

Un module peut être défini comme un groupe de fonctions ayant une cohésion forte et un couplage faible.

Couplage faible

pas de liens entre les données internes et des données manipulées par d’autres programmes ;

le module dit posséder ses propres zones de travail jamais utilisées par d’autres modules.

Liaisons externes (interface)

les données d’entrée/sortie sont des paramètres à passer au module ;

on définira de manière précise la structure des données d’entrée à passer au module, de même que la structure des données fournies en sortie.

Cohésion

la fonction doit être clairement identifiée et cohérente.

La modularité des programmes est une orientation poussée depuis plus de vingt ans, surtout avec l’orientation objet.

La fonction d’un module est l’ensemble des transformations appliquées par le module sur les données d’entrées pour produire les données de sorties, à chaque appel du module.

Pourquoi modulariser ? Il s’agit tout à la fois de faciliter la maintenance, d’optimiser l’architecture et de mettre en place les meilleures pratiques de mutualisation et de réutilisation.

La meilleure façon de résoudre un problème complexe est de le décomposer. Les programmes modulaires sont plus faciles à comprendre, documenter et maintenir. Ils fournissent des éléments interchangeables, réutilisables et combinables entre eux.

L’objectif est de réduire la complexité en restructurant le système en un assemblage de sous-systèmes plus simples qui peuvent être maintenus séparément. Le principe est de découper les programmes en modules, ou groupes de fonctions liées, découpage fondé sur l’observation qu’un module peut être défini comme un groupe de fonctions ayant une forte cohésion et un couplage faible. La modularité a pour bénéfices de faciliter la compréhension, la maintenance et la réutilisabilité, en particulier en autorisant la parallélisation des développements et des tests. Elle a également pour conséquence une meilleure portabilité.

La maintenance sera facilitée car une modification sur un module sera automatiquement répercutée dans tous les programmes qui l’appellent. Les modules permettent la création d’une bibliothèque de composants réutilisables.

L’application du principe de modularité du code, au niveau du développement, est l’étape-clé pour le rendre réutilisable. Le module étant un sous-programme, son autonomie est assurée par la force des choses (règles du langage de programmation).

Les spécifications externes (données d’entrée/sortie) et internes (règles de traitement) étant clairement définies, on pourra donner la programmation du module à toute personne compétente, même si elle ne connaît pas le reste du programme.

Les modules permettent la séparation des différentes composantes

de l’application (par exemple, séparation

données/traitements/affichage) afin de rendre leur développement indépendant les uns des autres.

En outre, via la modularisation, on peut envisager d’extraire les règles de gestion écrites en dur dans le code pour les rendre paramétrables dans un moteur de règles, à des fins de flexibilité métier.

Selon l’objectif des bénéfices recherchés par la modularisation d’un existant, le champ des techniques utilisées sera différent.

L’approche la plus étendue étant une recherche de modularisation applicative au niveau d’un système d’information, pour passer d’un patrimoine applicatif développés « en silos applicatifs », à une architecture d’assemblage de composants.

Si la modularisation vise une application seule, elle peut être ou technique – et dans ce cas on cherche à partager des traitements – ou fonctionnelle, et on cherche alors à mutualiser des fonctions. On passe au niveau « sémantique » (niveau conceptuel/abstraction) quand on cherche à extraire la logique métier (services métier ou règles de gestion) pour aller au-delà de l’application et pouvoir viser l’assemblage de composants métier.

Le tableau 8-2 illustre les différents niveaux de recherche de modularisation, les techniques possibles et les limites.

Tableau 8-2 identification de patrons d’algorithmes. d’endettement maximum, le montant de retraite moyen par