Parfois, la duplication de code est le résultat d'un "jeu de mots": deux choses se ressemblent, mais ne le sont pas.
Il est possible qu'une surabrégé excessif puisse briser la véritable modularité de votre système. Sous le régime de la modularité, vous devez décider "qu'est-ce qui est susceptible de changer?" et "qu'est-ce qui est stable?". Tout ce qui est stable est mis dans l'interface, tandis que tout ce qui est instable est encapsulé dans l'implémentation du module. Ensuite, lorsque les choses changent, la modification que vous devez effectuer est isolée de ce module.
Le refactoring est nécessaire lorsque ce que vous pensiez être stable (par exemple, cet appel API prendra toujours deux arguments) doit changer.
Donc, pour ces deux fragments de code dupliqués, je demanderais: un changement requis pour l'un signifie-t-il nécessairement que l'autre doit également être changé?
La façon dont vous répondez à cette question pourrait vous donner une meilleure idée de ce qu'est une bonne abstraction.
Les modèles de conception sont également des outils utiles. Peut-être que votre code dupliqué effectue une traversée d'une forme quelconque, et le modèle d'itérateur doit être appliqué.
Si votre code dupliqué a plusieurs valeurs de retour (et c'est pourquoi vous ne pouvez pas faire une méthode d'extraction simple), alors vous devriez peut-être créer une classe qui contient les valeurs renvoyées. La classe pourrait appeler une méthode abstraite pour chaque point qui varie entre les deux fragments de code. Vous feriez alors deux implémentations concrètes de la classe: une pour chaque fragment. [Il s'agit en fait du modèle de conception de la méthode de modèle, à ne pas confondre avec le concept de modèles en C ++. Alternativement, ce que vous regardez pourrait être mieux résolu avec le modèle de stratégie.]
Une autre façon naturelle et utile d'y penser est d'utiliser des fonctions d'ordre supérieur. Par exemple, créer des lambdas ou utiliser des classes internes anonymes pour que le code passe à l'abstraction. En général, vous pouvez supprimer la duplication, mais à moins qu'il n'y ait vraiment une relation entre eux [si l'un change, il en va de même pour l'autre], vous risquez de nuire à la modularité, de ne pas l'aider.
Personnellement, je l'ignore et je continue. Les chances sont que si c'est un cas étrange, il est préférable de le dupliquer, vous pourriez passer des années à refactoriser et le prochain développeur va jeter un coup d'œil et annuler votre changement!
la source
Sans exemple de code, il est difficile de dire pourquoi votre code n'a pas d'abstraction facilement identifiable. Avec cette mise en garde, voici quelques idées:
La plus grande difficulté de cet exercice est que votre fonction incorpore probablement trop de comportements non liés à un niveau d'abstraction donné, et vous devez gérer certains d'entre eux à des niveaux inférieurs. Vous supposez correctement que la clarté est la clé du maintien du code, mais rendre le comportement du code clair (sa condition actuelle) est très différent de rendre l'intention du code claire.
Faites en sorte que les petits morceaux de code soient abstraits en faisant en sorte que leurs signatures de fonction identifient le quoi, et les gros morceaux devraient être plus faciles à classer.
la source