DRY code non apparenté, mais presque identique

34

J'ai du code presque identique, mais utilise des types absolument différents, sans héritage entre eux, sur la variable principale. Plus précisément, j'écris un analyseur avec Roslyn pour C # et VB.NET, avec les types suivants:

Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax

Je me demande si, parce que le code fait la même chose, je devrais le garder aussi sec que possible, en séparant le moins possible en méthodes distinctes (mais identiques, à part le type), ou en les séparant complètement, car les deux méthodes sont: non lié et les modifications futures pourraient forcer une version à changer, mais pas l'autre (bien que cela soit peu probable)?

Edit: Un an plus tard, j’ai fait face au même problème et l’équipe de Roslyn m’a aidé à le résoudre: rédigez un cours de base qui utilise des génériques et qui a un TAttributeSyntaxparamètre qui effectue la majeure partie du travail. Ensuite, écrivez des classes dérivées avec le minimum de données nécessitant un type spécifique.

Hosch250
la source
Est-ce que cela fonctionnerait pour créer votre propre interface AttributeSyntax qui enveloppe les classes existantes mais vous donne l'héritage qui devrait être conceptuellement là?
Winston Ewert
7
Désolé si cela est évident, mais les génériques existent afin que vous n'ayez pas à vous répéter pour un code identique mais pour le type. Si ce n'est pas ce que vous vouliez dire, veuillez ignorer.
Davislor
@Lorehead En règle générale, je le ferais, mais il s'agit d'une méthode unique à laquelle est transmis un type qui contient le nœud en tant que charge utile à partir d'une méthode interne sur laquelle je n'ai aucun contrôle.
Hosch250
@ WinstonEwert, je vais examiner cela. Je ne suis cependant pas sûr de vouloir le faire pour tous les types C # / VB.NET.
Hosch250
1
Le refactoring impose de nombreux compromis et parfois même des paradoxes. Par exemple, un couplage lâche par rapport à DRY ou à des fonctions courtes, mais beaucoup d’entre elles par opposition à des fonctions plus longues et peu nombreuses. En fin de compte, c'est une bête difficile: votre objectif est la lisibilité et la maintenabilité. Vous devez penser comme un avatar qui voit votre code pour la première fois. Et parfois, vous essayez simplement de voir ce qui est meilleur. Le refactoring parfait n'est malheureusement pas possible.
phresnel

Réponses:

111

Vous ne faites pas DRY parce que quelqu'un l'a écrit dans un livre quelque part où il fait bon de le faire, vous le faites parce que cela présente des avantages tangibles.

Plus précisément de cette question:

Si vous vous répétez, vous pouvez créer des problèmes de maintenabilité. Si doStuff1-3 comporte tous du code structuré de la même manière et que vous corrigez un problème, vous pouvez facilement oublier de résoudre le problème ailleurs. De plus, si vous devez ajouter un nouveau cas à gérer, vous pouvez simplement passer différents paramètres dans une fonction plutôt que de les copier-coller partout.

Cependant, DRY est souvent poussé à l'extrême par des programmeurs intelligents. Parfois, pour ne pas vous répéter, vous devez créer des abstractions si obtuses que vos coéquipiers ne peuvent pas les suivre. Parfois, la structure de deux choses n’est que vaguement similaire mais suffisamment différente. Si doStuff1-4 est suffisamment différent pour ne pas vous répéter, vous devez écrire du code non naturel ou subir des réflexions de code astucieuses qui feront que votre équipe vous éblouira, alors vous pourrez peut-être vous répéter. Je me suis plié en quatre pour ne pas me répéter plusieurs fois de façon artificielle et j'ai regretté le produit final.

Donc, fondamentalement, ne pensez pas "oh mec, ce code est assez similaire, je devrais peut-être refactoriser pour ne pas me répéter". Pensez-vous que le refactoring pour que cette base de code réutilise des éléments communs rend le code plus facilement maintenable ou moins maintenable ? Ensuite, choisissez celui qui le rend plus facile à gérer.


Cela dit, étant donné que SRP et l’essai d’avoir de petites classes flexibles en général, il peut être judicieux d’analyser votre code pour cette raison , séparez des éléments de comportement qui utilisent des types génériques petites classes. Ensuite, vous découvrirez que certaines de ces classes sont en réalité totalement identiques (et pas uniquement identiques), puis vous pouvez créer une boîte à outils au cas où vous souhaiteriez en ajouter Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntax.

durron597
la source
32
TL; DR - DRY est un moyen de parvenir à une fin. Concentrez-vous sur la fin, pas sur les moyens. Si je pouvais voter à deux reprises le Lego Man, je le ferais.
Une remarque importante: si vous vous répétez, mentionnez toujours dans le commentaire tous les autres lieux à visiter lorsque le code répété change. Non seulement cela réduit les risques de désynchronisation, mais il indique également à quel point la répétition vous cause de la douleur lors de l'entretien.
Xion