Design smell : code dupliqué

Posted by Alexandre Heimburger Sun, 09 Mar 2008 13:25:00 GMT

 Je commence aujourd’hui une série de billets sur les "design smells". Derrière cette expression se cachent les problématiques qui ont poussé un jour le Gang Of Four (Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides) à écrire les premiers design patterns.

Je lis beaucoup d’articles traitant de ces recettes magiques et souvent le constat est le même : on apprend à faire un template, une factory, un proxy….mais on ne sait pas quand les utiliser. Alors on tombe dans le syndrome de la "paternite aiguë" qui consiste à vouloir les implémenter systématiquement et à toutes les sauces. Et là c’est le drame. Ce qui aurait pu être codé en quelques ligne requiert 4 classes, une interface, de la réflexion…. L’exemple paraît extrême mais on le retrouve souvent chez les développeurs qui viennent de lire "Head First in Design Pattern" mais qui n’avaient pas forcement de notions d’architecture avant cela. Les conséquences, des coûts de développement supplémentaires et une frustration de la part des développeurs qui se rendent vite compte que rien est magique.

Voilà donc pourquoi j’apprécie l’approche "Code Smells" qui apprend tout d’abord à identifier les portions de code mal écrites et les besoins de refactorisation. Le design pattern est alors un outil et non un objectif en soi.

Let’s rock !

Aujourd’hui, ce billet sera dédié au Smell le plus facile à identifier : "le code dupliqué"

Première chose, pourquoi essayer de lutter contre la duplication de code :

- tout d’abord parce que plus le code est compact, plus il est facile à tester et à maintenir
- imaginons qu’il y ait un bug dans une des portions dupliquées. Souvent, la correction n’est pas reportée dans les autres portions et le même bug risque de réapraître plus tard. Il sera considérer comme une régression, gloups…

On peut distingue 2 sortes de code dupliqué : le code dupliqué explicite, le code dupliqué subtil.

Le code dupliqué explicite est le plus facile à identifier. On retrouve les mêmes lignes de code à plusieurs endroits.

Le code dupliqué subtile quant à lui est bien plus fourbe car il s’agit de plusieurs portions de code exécutant les même traitements, mais codé différemment.

Exemple 1 :

La même méthode est implémentée de manière presque similaire dans 2 sous-classes. On retrouve alors des lignes de code communes et des lignes de code spécifiques.
Une solution possible est d’utiliser le pattern "Form template method" qui consiste à créer une méthode ayant la même signature dans la classe mère. Cette implémentation contiendra le code commun puis déléguera à ses filles les comportements spécifiques via des méthodes abstraites (hook)

Un exemple de code ici.

Exemple 2 :

Si une classe contient plusieurs constructeurs avec du code dupliqué, l’utilisation du pattern "Chained Constructor" peut résoudre le problème.
En exemple de code ici.

Exemple 3 :

2 classes exécutent sensiblement les même traitements mais n’implémentent pas d’interface commune. Si les 2 interfaces ne peuvent pas être mergées, une solution peut être de créer une interface commune à ces 2 classes afin de simplifier le code appelant. L’utilisation du pattern "Unify interface with Adapter" permet de créer un point de jonction.
Un exemple de code ici.

Exemple 4 :

On introduit souvent une logique conditionnelle dans le cas où un objet est nul. Et cette logique est répercutée dans tout le code. En utilisant le pattern, "Null Object", cette duplication peut être évitée.
Un exemple de code ici.

Et bien voilà, 4 exemples de Smell, 4 solutions…et non le contraire.

Dans le prochain billet, je parlerais d’un autre cauchemar de développeur : les longues méthodes, ou comment éviter d’avoir des méthodes de 400 lignes qui deviennent très vite impossible à maintenait.