Il est bien connu que la présence de code dupliqué a un impact négatif sur le développement et la maintenance des logiciels. En effet, un inconvénient majeur est que lorsqu'une instance de code dupliqué est modifiée pour corriger des bugs ou ajouter de nouvelles fonctionnalités, ses homologues doivent être modifiées en même temps.
La cause la plus courante de code dupliqué est le copier-coller, où le code source est exactement le même à deux endroits ou plus. Cette pratique est déconseillée dans de nombreux articles, livres et sites web. Cependant, il n'est pas toujours facile de suivre les recommandations, et les développeurs choisissent souvent la solution facile : copier-coller.
Il existe de nombreux outils pour détecter ce genre de code cloné ; CCFinderX est l'un des outils open source intéressants disponibles. CCFinderX est un détecteur de clones de code qui détecte les clones de code (fragments de code dupliqués) dans des fichiers sources écrits en Java, C/C++, COBOL, VB et C#. Il permet une personnalisation côté utilisateur d'un préprocesseur et fournit une analyse interactive basée sur des métriques.
Utiliser l'outil approprié permet de détecter facilement le code dupliqué produit par des copier-coller ; cependant, il existe des cas où le code cloné n'est pas trivial à détecter.
Le code dupliqué cachéCas 1 : le code copié-collé puis modifié.
Comme décrit ci-dessus, le principal problème du code copié-collé est que lorsqu'une instance de code dupliqué est modifiée, ses homologues doivent être modifiées en même temps. Malheureusement, ce n'est pas toujours le cas, et les instances de code dupliqué deviennent différentes.
Pour éviter ce genre de code dupliqué caché, n'hésitez pas à utiliser un outil comme CCFinderX pour découvrir les instances de code dupliqué, et au minimum marquez-les en ajoutant des commentaires si vous n'avez pas le temps de refactoriser votre code. C'est très utile lorsqu'un développeur tente de modifier une instance de code dupliqué : il sera averti que le même code existe ailleurs. En revanche, si le développeur ignore la duplication, il peut ne modifier qu'une seule instance, et il deviendra très difficile de détecter plus tard le code dupliqué modifié.
Cas 2 : les fonctionnalités similaires
Les copier-coller ne sont pas la seule source de code dupliqué ; une autre source est l'implémentation indépendante de fonctionnalités similaires.
Voici une brève description de cette seconde source de code dupliqué, tirée de Wikipédia:
Functionality that is very similar to that in another part of a program is required and a developer independently writes code that is very similar to what exists elsewhere. Studies suggest, that such independently rewritten code is typically not syntactically similar.Traquer le code dupliqué caché
Lorsque le code dupliqué n'est pas exactement le même, aucun outil ne peut vous donner des résultats fiables : il peut seulement signaler du code potentiellement dupliqué, et c'est la responsabilité du développeur de vérifier s'il s'agit vraiment de code cloné ou simplement d'un faux positif.
Chaque outil utilise un algorithme spécifique pour traquer ce genre de code dupliqué. Nous n'avons pas testé tous ces outils, mais je pense que la plupart méritent d'être essayés au moins une fois : ils pourraient vous donner des résultats intéressants qui vous aideront à améliorer la conception et l'implémentation de votre code, comme nous le verrons plus loin dans cet article.
Dans notre cas, nous utiliserons un algorithme qui consiste à définir des ensembles de méthodes qui utilisent les mêmes membres, c'est-à-dire appellent les mêmes méthodes, lisent les mêmes champs et écrivent les mêmes champs. Nous appelons ces ensembles des suspect-sets. Les suspect-sets sont triés par nombre de membres communs utilisés.
CppDepend implémente cet algorithme sous forme de Power-Tool CppDepend. Les Power-Tools sont un ensemble d'outils open source basés sur CppDepend.API. Le code source des Power-Tools se trouve dans $CppDependInstallPath$\CppDepend.PowerTools.SourceCode\CppDepend.PowerTools.sln.
Voyons l'efficacité de cet algorithme pour trouver du code dupliqué dans la base de code du moteur 3D Irrlicht.
Étude de cas : le moteur 3D Irrlicht
Le moteur Irrlicht est un moteur 3D temps réel open source et haute performance écrit en C++. Il est entièrement multiplateforme.
Voici deux exemples de code dupliqué suspect qui ont été détectés :
1- Code dupliqué exact
Dans ce cas, les 18 méthodes détectées utilisent les mêmes 3 méthodes, lisent les mêmes 2 champs et écrivent les mêmes 9 champs.

Après vérification du code source de ces méthodes, elles s'avèrent contenir du code dupliqué exact. Cependant, d'autres outils sont mieux adaptés pour détecter ce genre de duplication, et notre algorithme n'apporte pas de valeur supplémentaire lorsqu'il s'agit de détecter des clones exacts.
2- Fonctionnalité similaire
Voici une seconde duplication suspectée : elle concerne quatre méthodes qui utilisent les mêmes 11 méthodes, lisent les mêmes 6 champs et écrivent les mêmes 2 champs.

Après vérification du code source de ces quatre méthodes, le code n'est pas exactement le même. Cependant, elles implémentent le même algorithme de mise en page, donc dans ce cas je recommanderais une refactorisation.
Pour mieux expliquer ce cas, voici la relation entre les classes impliquées dans le code dupliqué :

OnSetConstants est déclarée dans l'interface IShaderConstantSetCallBack et implémentée par toutes les classes dérivées. Les quatre implémentations ont le même algorithme de mise en page, et dans de tels cas le pattern template method est une bonne solution pour refactoriser l'implémentation existante.
En testant cet algorithme sur de nombreux projets C++ open source, nous avons été très surpris de constater que de nombreux cas de code dupliqué ressemblent à celui-ci, et que le pattern template method est rarement utilisé.
Conclusion
Traquer le code dupliqué est très utile pour améliorer à la fois l'implémentation et la conception de vos projets. Heureusement, de nombreux outils existent pour détecter le code cloné, et c'est une bonne idée d'exécuter l'un de ces outils périodiquement et, au minimum, de marquer les instances dupliquées.
