web-dev-qa-db-fra.com

Pourquoi le code inutilisé doit être supprimé?

J'ai entendu à plusieurs reprises que le code inutilisé doit être supprimé du projet. Cependant, il n'est pas clair pour moi "pourquoi?".

Mes points pour ne pas supprimer qui sont:

  • Le code est déjà écrit et les efforts sont dépensés
  • Le code peut être testé sur un environnement syntaxique et réel
  • S'il est bien organisé (groupé, package séparé, faiblement couplé, etc.), cela ne vous dérange pas sur l'analyse globale du code ou la refactorisation
  • Le code pourrait être utilisé à l'avenir
  • Une fois supprimé, l'auteur peut se sentir mal à l'aise

Quelqu'un pourrait-il expliquer les avantages de la suppression (ou de la conservation) du code inutilisé?

Merci d'avance!

86
Alex Stamper

Voici quelques raisons pour lesquelles le code inutilisé doit être supprimé:

  • Pour toute nouvelle personne travaillant sur un projet, elle doit non seulement comprendre le code de travail, mais également comprendre le matériel inutilisé. C'est du temps perdu et cela crée de la confusion.

  • Il y a un danger que quelqu'un fasse un jour un changement qui impliquera par inadvertance le code "dormant" et peut introduire des bogues. Je sais que c'est arrivé sur des projets sur lesquels j'ai travaillé.

  • Le maintien de tout code est une charge administrative. En préservant l'ancien code redondant, cette charge est accrue. Par exemple, la fusion des modifications dans la branche principale devient plus difficile car il y a plus de code à traiter et plus de possibilité de faire une erreur.

  • Ce qui se passe au fil du temps, c'est que de plus en plus de vieux code inutilisé sont ajoutés à la base de code. Cela augmente la confusion, les malentendus potentiels et les frais administratifs.

  • Il est très peu probable que le code inutilisé soit réutilisé. Avec le temps, cette possibilité de réutilisation diminue. Si le code doit être supprimé et est considéré comme suffisamment important, le code peut être dérivé et documenté.

  • Tout sentiment personnel qu'un codeur peut avoir à propos du code sur lequel il a travaillé dur est compréhensible. Mais une partie du professionnalisme exige que ces pensées soient mises de côté pour le mieux. Le temps ne représente personne et il n'y a pas de place pour conserver le code historique dans une base de code fonctionnelle.

153
suspectus

@suspectus a fait un excellent travail de présentation des raisons de la suppression du code; Je voudrais m'adresser à vos puces individuelles pour conserver le code.

  • Le code est déjà écrit et les efforts sont dépensés

Mais si le code déjà écrit n'est pas utilisé, cela ne coûte que sans valeur (future). C'est un effort investi en vain, et la conservation du produit inutilisé de ces efforts ne valide pas ces efforts. Nous gardons le code parce qu'il est utile, maintenant, pas comme une sorte de mémorial aux efforts des auteurs.

  • Le code peut être testé sur un environnement syntaxique et réel

Je suis désolé, je ne sais pas ce que tu veux dire par là.

  • S'il est bien organisé (groupé, package séparé, faiblement couplé, etc.), cela ne vous dérange pas sur l'analyse globale du code ou la refactorisation

S'il existe dans la base de code, aussi bien organisé soit-il, il contribue à la charge de maintenance et de compréhension. Certes, il peut être organisé de manière à être moins d'un fardeau, mais s'il a disparu, ce n'est pas du tout un fardeau.

  • Le code pourrait être utilisé à l'avenir

Dans l'école Agile, nous disons YAGNI : Vous n'en aurez pas besoin. Oui, vous pourriez éventuellement l'utiliser à l'avenir, mais nous ne savons pas assez aujourd'hui sur les besoins de demain pour pouvoir prédire cela avec toute sorte de fiabilité. Penser le contraire, c'est de l'arrogance qui tend vers l'orgueil. Ce que nous pouvons savoir de demain, c'est: nous voulons que notre base de code soit facile à modifier, et le code inutilisé nuit à cette caractéristique.

  • Une fois supprimé, l'auteur peut se sentir mal à l'aise

L'auteur doit s'en remettre. Nous avons tous écrit des choses qui se sont avérées ne pas être utiles - beaucoup mieux pour pouvoir pointer vers un corps de code qui est tout utilisé (parce que la cruauté inutilisée a été supprimée) que vers un corps de code dans lequel vous pouvez dire de quelques méthodes, "et que celle-ci est réellement utilisée!"

23
Carl Manaster

N'est-il pas assez difficile de récupérer du code et de comprendre l'intention, mais maintenant vous devez déterminer quelles parties ne sont pas utilisées?

15
kenny

Le code est déjà écrit et les efforts sont dépensés

C'est également inutile. Si vous ne l'utilisez pour rien, il est (par définition) inutile, peu importe ce qu'il fait ou combien d'efforts y ont été consacrés.

Le code peut être testé sur un environnement syntaxique et réel

Si c'est inutile, c'est quand même inutile même si vous avez des tests dessus. Si le code est inutile, les tests pour lui devraient également être inutiles (donc garder le code commenté là, crée une ambiguïté - gardez-vous les tests? Si vous aviez le code client du code commenté, commentez-vous également le code client? )

S'il est bien organisé (groupé, package séparé, faiblement couplé, etc.), cela ne vous dérange pas sur l'analyse globale du code ou la refactorisation

Mais non. Tous vos outils (contrôle de source, analyse statique, extracteur de documentation, compilateur, etc.) fonctionneront plus lentement, car ils doivent traiter plus de données (et une partie plus ou moins grande de ces données est du bruit).

Si le code n'est pas bien organisé d'autre part, il gâchera l'analyse statique, la refactorisation et toutes les autres.

Vous introduisez du bruit dans l'entrée de vos outils et espérez qu'ils y feront face correctement.

Et si votre outil d'analyse statique calcule un rapport commentaires/code? Vous venez de tout gâcher, avec quelque chose qui était pertinent jusqu'à hier (ou chaque fois que le code était commenté).

Le plus pertinent de tous, les blocs de code commentés introduisent des retards dans la compréhension du code pour la maintenance et le développement ultérieur et ces retards coûtent presque toujours beaucoup. Demandez-vous ceci: si vous avez besoin de comprendre la mise en œuvre d'une fonction, que préférez-vous regarder? deux lignes de code clair, ou deux lignes de code et encore vingt-six commentaires qui ne sont plus d'actualité?

Le code pourrait être utilisé à l'avenir

Si c'est le cas, vous le trouverez dans le SCM de votre équipe.

Si vous utilisez un SCM compétent et que vous vous y fiez pour conserver le code mort (au lieu d'encombrer la source), vous devriez voir non seulement qui a supprimé ce code (auteur de la validation), mais pour quelle raison (message de validation) et quels autres des modifications ont été apportées en même temps (le reste des différences pour ce commit).

Une fois supprimé, l'auteur peut se sentir mal à l'aise

Alors?

Vous êtes (je suppose) une équipe entière de développeurs qui sont payés pour créer le meilleur logiciel que vous savez, pas "le meilleur logiciel que vous savez sans blesser les sentiments de X".

Cela fait partie de la programmation, la plupart du code écrit sera finalement éliminé; par exemple, Joel Spolsky a déclaré à un moment donné que pour son entreprise, environ 2% du code écrit était en production.

Si vous donnez la priorité à l'ego des développeurs sur la qualité de la base de code, vous sacrifierez la qualité de votre produit, pour ... quoi exactement? Préserver l'immaturité de vos collègues développeurs? Protéger les attentes irréalistes de vos collègues?

Edit: J'ai vu une raison valable de laisser du code commenté dans la source, et c'est un cas très spécifique: lorsque le code est écrit sous une forme bizarre/non intuitive et la manière propre de réécrire ça ne marche pas pour une raison vraiment subtile. Cela ne devrait également être appliqué qu'après une tentative répétée a été faite pour corriger le problème et chaque fois que la tentative a réintroduit le même défaut. Dans un tel cas, vous devez ajouter le code intuitif commenté en tant que commentaire et expliquer pourquoi cela ne fonctionne pas (afin que les futurs développeurs ne tentent pas à nouveau la même modification):

// note by <author>: the X parameter here should normally
// be a reference:
// void teleport(dinosaur& X);
// but that would require that we raise another dinosaur and
// kill it every twelve hours
// as such, the parameter is passed by value
void teleport(dinosaur X);
13
utnapistim
  • Peur. Cela fait que l'équipe s'inquiète davantage et produit moins. La quantité de peur augmente de façon exponentielle lorsque davantage de code mort est introduit. "Nous ne savons pas si ce bit est utilisé, donc nous n'osons pas le retirer ou le toucher."
  • Changements radicaux. Si quelque chose qui doit être changé partout dans le système existe également dans le code mort, le changez-vous? Il est très difficile de savoir s'il n'est certainement pas utilisé quelque part, c'est donc toujours un risque. Et même s'il ne cassait rien, le code mort fonctionnerait-il du tout s'il était réutilisé après ce changement?

    Lorsqu'il s'agit d'un changement radical, les développeurs devront également vérifier chaque endroit qui contient le code et dans le cas d'un code mort, c'est redondant. Et les vérifier prend plus de temps lorsque le code est mort car il est difficile de vérifier qu'il n'est utilisé nulle part.

  • Charge mentale. Chaque fois que vous devez vous demander si quelque chose est utilisé ou si vous devez faire quelque chose pour le code mort, cela prend une partie de votre puissance cérébrale.
  • Chasse à l'oie sauvage. "J'ai besoin d'un exemple sur la façon d'utiliser Foobar. Oh, c'est à ces endroits dans la base de code. Je vais vérifier le premier hit et trouver où cela se trouve dans l'interface utilisateur. Hmm ... Je ne le trouve nulle part."
  • Rapports gonflés (par exemple, combien de lignes de code, classes, routines, modifications). Fausse la visibilité du projet et les décisions sur les parties de la base de code à travailler et les estimations des futurs projets.
  • Confiance affaiblie sur la base de code. Cela peut entraîner plus de temps consacré aux tâches redondantes et interrompre le flux d'utilisation de la base de code. Les développeurs devront peut-être vérifier très soigneusement que tout ce qu'ils utilisent fonctionnera comme ils le devraient.

Il est extrêmement précieux si vous savez qu'une partie de la base de code n'est pas utilisée car vous pouvez alors la supprimer. Si vous le laissez rester à l'avenir, il peut être difficile ou presque impossible d'être certain qu'il n'est pas utilisé. Par exemple, certaines des choses qui utilisent le code de façon surprenante: réflexion, appel dynamique de routines concaténées à partir de chaînes, eval, framework magic.

Cependant, s'il existe une forte probabilité que le code soit utilisé à l'avenir, il est plus facile de l'ajouter s'il se trouve juste le long de l'autre code plutôt que dans le système de contrôle de version. Vous ne vous souvenez peut-être pas des mots que le code avait après un certain temps, il peut donc être très difficile de trouver le code dans les entrailles du VCS. Mais je ne laissais le code mort exister que rarement et même alors je commentais le code.

9
Heikki Naski

Le code mort pollue votre code

Le code mort diminue la compréhension et la lisibilité.

Les meilleurs codes sont toujours réutilisés, et si vous avez des codes morts, cela réduit la réutilisabilité

Nous sommes guidés par une approche modulaire du codage, où nous concevons des codes pour l'interaction avec nos collègues programmeurs, pas pour une machine. Nous devons mettre le plus d'énergie pour lui permettre de comprendre facilement notre code. La machine ira quand même bien.

Un code mort ou commenté est comme de faux panneaux de signalisation qui ne font que confondre les gens, alors évitez-le à tout prix.

8
Jimmy
  • Le code inutilisé est un espace de recherche plus grand que vous pouvez lire et tout ce qui analyse généralement votre code. Par exemple, un compilateur, IDE, trouver dans un fichier, débogage, analyse statique, plus à examiner, inclusion de fichier, extraction de VCS, etc. Cela ralentit ces processus et ajoute un bruit important.
  • Le code non utilisé n'est pas toujours un code mort. Il peut s'exécuter dans certaines circonstances. Cela peut non seulement offrir un vecteur de bogues et de problèmes de performances, mais peut également être un problème de sécurité. En ce qui concerne les performances, cela peut s'exprimer de manière inattendue, comme des téléchargements plus importants.
  • Le code inutilisé engendre du code inutilisé. Si vous supprimez un appel de fonction, puis recherchez les utilisations de cette fonction pour voir si elle est toujours nécessaire, vous pouvez voir une correspondance avec le code inutilisé précédent et supposer que vous pouvez le conserver. Plus vous avez de code inutilisé, plus il y a de sauts pour déterminer si le code n'est pas utilisé.
  • Le code non utilisé finit souvent par devoir être conservé. Disons que A et B dépendent de C. Parmi ceux-ci, B n'est pas utilisé. Vous modifiez C, puis B ne compilera pas parce que vous avez supprimé un membre d'une structure en C que B requis, vous devez maintenant corriger B ou le supprimer activement de la compilation. Vous auriez dû simplement le retirer.

Cette liste peut sembler simple, mais chacune de ces manifestations se manifeste de centaines de manières différentes en ajoutant une traînée qui se synergise tout au long du processus de développement. L'inefficacité peut souvent être prouvée ou démontrée de manière simple et mathématique.

En réponse à vos points ...

  • Le code est déjà écrit et les efforts sont dépensés

Mais elle doit souvent être maintenue. Il apparaîtra également dans des éléments tels que la recherche dans un fichier.

  • Le code peut être testé sur un environnement syntaxique et réel

Je ne sais pas ce que tu veux dire par celui-ci. Je pense que c'est la même chose que la dernière. Vous voulez dire que le code est déjà testé et le nettoyer peut signifier qu'il doit être retesté. C'est un coût qui en vaut généralement la peine car il sera rentable dans 90% des cas et pour éviter qu'il n'ait dû être nettoyé avant la mise en production. Presque tout le code a deux itérations, faites-le fonctionner, nettoyez-le. La raison doit être testée deux fois parce que quelqu'un a sauté la dernière étape. Si votre code est également trop cher pour vérifier le diff, tester (ce qui est probablement le cas s'il est en désordre avec beaucoup de code inutilisé), etc., c'est un autre problème.

  • S'il est bien organisé (groupé, package séparé, faiblement couplé, etc.), cela ne vous dérange pas sur l'analyse globale du code ou la refactorisation

Votre code devrait être comme ça de toute façon mais cela n'atténue que modérément le problème. C'est l'argument le plus étrange d'entendre que quelque chose doit être organisé mais impur. Il est normal d'essayer de garder le code modulaire et de réduire les dépendances, mais vous voulez également du code réutilisable et si tous vos modules sont un îlot, il est probable que vous n'ayez pas été SEC. Vous pouvez également vous retrouver à faire un découplage excessif qui ne fait rien mais atténue le problème du code désordonné inutilisé.

  • Le code pourrait être utilisé à l'avenir

Beaucoup de gens préfèrent le code écrit. S'il n'est pas utilisé maintenant, c'est un poids mort et en réalité, lorsque vous suivez ce chemin, souvent, seule une fraction du code inutilisé devient du code utilisé. Selon toute probabilité, le code inutilisé n'est pas susceptible d'être un code utilisable ou utilisé. Le code le plus susceptible d'être réutilisé est le code déjà utilisé qui fait quelque chose.

Le pire, c'est que le code inutilisé n'a pas de but. Quand quelqu'un arrive et doit changer quelque chose qui finit par avoir un impact sur le code inutilisé, il va être perplexe assis là à essayer de comprendre ce que ce code inutilisé sans but doit faire.

Il est facile pour les gens de ressentir cela au début, car le code demande beaucoup d'efforts. Cependant, une fois maîtrisé et habitué, le code devient comme faire du vélo. Vous constaterez que le coût de l'écriture d'un tel morceau de code diminue le coût de son maintien.

  • Une fois supprimé, l'auteur peut se sentir mal à l'aise

C'est le problème de l'auteur. D'une part, il est égoïste de laisser autour de charges de code inutilisé pour les autres. D'autre part, si un auteur met ses sentiments sur la qualité du code, il ne devrait probablement pas coder. Vous descendez la route avec cela, vous ne pouvez pas réparer leur code lorsqu'il est cassé, car cela nuira à leurs sentiments. Ce n'est pas bon signe si quelqu'un est attaché au code simplement parce que c'est le leur plutôt que parce que c'est bon. Un auteur devrait se sentir heureux que son code soit nettoyé. C'est comme si quelqu'un sortait vos poubelles pour vous et les jetait à la poubelle.

Je serais sur la lune si quelqu'un faisait ça pour moi. Ce qui pourrait aider à surmonter ces sentiments, c'est au lieu d'attendre que quelqu'un d'autre le fasse, essayez de le faire vous-même. Continuez à réécrire de manière itérative un morceau de code que vous avez fait, en le rendant plus performant, plus concis, avec moins d'excès et plus flexible mais avec moins de code à chaque fois. Essayez de ne pas vous sentir bien dans la quantité de code, mais dans tout ce que vous pouvez réaliser avec si peu de code. C'est difficile de monter de niveau et une fois que vous avez fait cela, tout votre code sortira à un bon niveau de suivi, il n'aura donc pas besoin d'être nivelé aussi souvent.

3
jgmjgm

Êtes-vous sûr que le code n'est pas utilisé?

Il ne suffit pas de vérifier que le code compile toujours. En C++, si vous supprimez un "inutilisé" méthode définie implicitement comme operator= vous n'obtiendrez pas d'erreur de compilation, la classe commencera silencieusement à utiliser une implémentation par défaut (potentiellement incorrecte). En Java ou C # le code peut être utilisé via la réflexion. Dans les langages orientés objet, l'héritage peut jouer un rôle (la classe de base peut maintenant être appelée). Dans presque tous les langages, une autre fonction surchargée peut avoir pris le relais.

Vérifiez l'âge du code dans le contrôle de version, pas seulement qu'il n'est pas utilisé. J'ai vu du code qui semblait inutilisé mais qui venait d'être validé, et qui était en fait la première étape du projet d'un autre développeur.

Supprimer agressivement le code inutilisé

Vous payez pour maintenir le code:

  • Correction de builds cassés (temps d'ingénierie). Nous avons récemment eu une chaîne compliquée de #include changer, introduisant une nouvelle surcharge du code inutilisé, conduisant à un mal de tête de taille raisonnable pour chaque ingénieur d'une équipe de dizaines de développeurs.
  • Dans les ressources de la machine sur les tests (en supposant que vous avez des builds auto-testés en continu). Mon équipe a récemment examiné tous nos tests les plus lents, et beaucoup d'entre eux étaient sur du code autrement inutilisé. Les ingénieurs exécutant des tests localement ou dans le cadre d'une intégration continue attendent des tests sur du code inutilisé.
  • En termes de lisibilité (temps d'ingénierie à nouveau). Vos fichiers d'en-tête représentent une API. S'ils incluent des fonctions que personne ne voudrait utiliser mais que tout le monde doit lire, la courbe d'apprentissage de votre code est d'autant plus difficile.
  • Dans les recherches de code (temps d'ingénierie à nouveau). Souhaitez-vous nettoyer votre maison, votre disque dur ou Google Drive? Plus vous recherchez un domaine, plus il est important qu'il ait un contenu pertinent pour éviter les faux positifs (ou vous utilisez une recherche plus sophistiquée comme un moteur de recherche Web).

Je dirais que pratiquement tout le code écrit par le développeur moyen n'est pas utilisé sur un horizon de cinq ans, donc cette activité ne s'arrête jamais . Ne laissez pas cela être vous; n'écrivez que du code de haute qualité et absolument nécessaire.

2
davidvandebunte

Cette discussion a plusieurs années, mais je suis juste tombée dessus ...

Une chose que je n'ai pas vue mentionnée est le travail qui doit être engagé pour supprimer le code inutilisé. Dans de nombreux cas, le temps et les efforts nécessaires pour supprimer le code inutilisé ne sont pas de nature anodine, et il y a généralement des coûts supplémentaires pour tester et documenter le système refactorisé. Juste une autre chose à considérer dans le processus de décision.

2
RonE

Tout d'abord, vous devez toujours utiliser un outil de contrôle de code source pour gérer vos projets et donc supprimer le code inutilisé est une bonne pratique car vous pouvez toujours revenir en utilisant le code source pour obtenir le code supprimé. Pour moi, la raison pour supprimer le code inutilisé est que seule la personne qui sait que le code est inutilisé le connaît, quelqu'un d'autre dans l'équipe rencontrera ce code et essaiera de comprendre ce qu'il fait et comment il s'intègre dans l'ensemble de l'application et se sentira déçu après tant d'efforts que le code ne soit pas utilisé du tout :)

2
Ankur

Je pense que vous pouvez avoir deux cas: - code d'application: s'il n'est pas utilisé, il n'est peut-être pas testé et non maintenu au fil du temps, peut-être que vous pouvez passer à un "référentiel de code interne" - Code API: si vous écrivez une bibliothèque, alors à mon humble avis c'est un meilleur choix pour le maintenir mais dans votre processus de développement actif

2
Antonello Pasella