Code inutile dans votre source

34

J'en ai entendu parler par des codeurs expérimentés et j'en ai moi-même vu certaines. Il semble qu'il y ait plus que quelques exemples de programmeurs écrivant du code inutile. Je vais voir des choses comme:

  • Appels de méthode ou de fonction qui ne font rien de valeur.
  • Contrôles redondants effectués dans un fichier de classe, un objet ou une méthode distinct (e).
  • if déclarations qui évaluent toujours à vrai.
  • Des fils qui se détachent et ne font rien d’important.

Juste pour en nommer quelques-uns. On m'a dit que c'était parce que les programmeurs voulaient délibérément confondre le code afin de donner leur propre valeur à l'organisation ou s'assurer de la fidélité des activités dans le cas de travail sous-traité ou sous-traité.

Ma question est. Est-ce que quelqu'un d'autre a vu un code comme celui-ci? Quelle était votre conclusion était pourquoi ce code était là?

Si quelqu'un a écrit un code comme celui-ci, pouvez-vous expliquer pourquoi?

Ali
la source
4
if (false) {...}les blocs sont parfaits pour commenter le code! </
sarcasm
18
N'attribuez jamais à la malice ce qui s'explique de manière adéquate par la stupidité , en particulier dans le développement de logiciels où les piratages rapides temporaires sont rarement temporaires.
Langage sauvage
1
@ dlras2 twist twist: #DEFINE false true :)
Silviu Burcea

Réponses:

17

J'ai entendu des développeurs qui essayaient de rendre leurs réalisations de codage plus complexes qu'elles ne le sont réellement. Je n'ai jamais entendu personne l'admettre, mais j'ai vu un code qui répond à vos critères, qui a été créé intentionnellement pour éviter la hâte ou de mauvaises pratiques et non le sabotage. Le code entourant le code maligné peut avoir été modifié au point où une fonction particulière n'est plus utile.

Quelqu'un devrait voir ce code de première main avant de conclure que seul ce développeur peut gérer la complexité. La plupart des gestionnaires et autres hommes d’affaires arrivent à cette conclusion parce qu’ils ne comprennent aucun type de code et ne veulent pas pourvoir au poste.

JeffO
la source
2
Je suis enclin à vous donner la bonne réponse dans ce cas car une partie du code que je vois ne peut tout simplement pas être involontaire ... pas à moins que quelqu'un ait été élevé quand il a codé et pensé que ce serait juste drôle! Je crois que d’autres ont également des raisons valables d’utiliser du code inutile, mais le code que je vois concerne des projets sur lesquels quelques personnes ont travaillé et je suis le premier type, en dehors de l’équipe de développement originale, à y travailler. Je dois dire que cela semble être un cas de complexité ajouté au choc et à la crainte.
Ali
18
@ Ali: n'attribuez jamais à la malveillance ce qui s'explique mieux par l'incompétence. En d'autres termes, le code a probablement évolué vers ce genre de désordre, car personne n'a eu le courage de prendre le temps de le regarder et de voir ce qu'il fait réellement. Tout cela ressemble à un tas de solutions rapides appliquées, encore et encore, jusqu'à ce que tout ce qui reste est un tas de beurk.
Rapidement maintenant
1
+1 pour @quickly_now. C'est généralement ce qui finit par arriver; tout le monde a peur de toucher à tout ce qui "fonctionne" de peur de le casser (ou, Dieu ne le préserve pas, prendre plus de temps pour améliorer le code! L'horreur!). Donc, le code pourrit et finit par s'effondrer et finalement s'effondre de nombreuses années plus tard.
Wayne Molina
@Ali, il est arrivé que du code qui semble le plus sémantique et le plus raisonnable soit décrit comme si je pensais que c'était drôle ou ridicule. Et inversement, je vois le code de quelqu'un d'autre. Vous ne savez jamais qui est fou, et la plupart du temps, il s’agit simplement d’expériences et de préférences. (ne parle pas de code objectivement mauvais ici, mais simplement que de telles descriptions sont facilement
diffusées
73

Je n'ai pas vu le code comme celui-ci mais j'ai vu le code qui a l'air inutile ou inutile pour les autres raisons:

  1. Rétrocompatibilité. Vous avez trouvé une bien meilleure façon de faire les choses, mais vous devez conserver l'ancienne API / fonction (qui n'est pas très utile pour le moment) car un module tiers peut utiliser cette API / cette fonction à des fins diverses. Même si la fonction ne fait rien d'utile, son absence peut casser du code.

  2. Codage défensif. Vous savez que les vérifications dans ce code sont inutiles parce que cela a déjà été vérifié ailleurs. Mais que se passe-t-il si quelqu'un modifie ce code ailleurs et supprime ou modifie les contrôles afin qu'ils ne correspondent plus à vos conditions préalables?

  3. Croissance organique. Au fil des ans, dans les grands projets, beaucoup de choses ont changé, et il s'avère que certaines méthodes utilisées auparavant ne sont plus utilisées, mais personne ne s'est donné la peine de les supprimer, personne ne surveillant si cette méthode est utilisée ou non, elles ont simplement refactorisé leurs morceaux de code et par hasard, ils se sont tous arrêtés pour utiliser cette méthode. Ou des conditions qui avaient autrefois un sens mais dont l'application avait été refactorisée ailleurs, de sorte que cette condition était toujours vraie, mais que personne ne prenait la peine de le supprimer.

  4. Sur-concevoir. Les gens pourraient coder certaines choses "au cas où nous en aurions besoin" et n'en auraient jamais réellement besoin. Comme "générons un fil au cas où nous aurions du travail hors ligne" et que personne ne demande à faire quoi que ce soit hors connexion et que le programmeur l'oublie et passe à d'autres projets (ou peut-être même à une autre société) et que le code y reste pour toujours parce que personne ne sait pourquoi il est là ou s'il est prudent de l'enlever.

Ainsi, bien que je ne l'aie jamais vu sortir d'une approche malicieuse ou malavisée en matière de sécurité d'emploi, j'ai souvent vu cela se produire comme un résultat naturel du développement logiciel.

StasM
la source
22
Je pense que n ° 3, la croissance organique explique une grande partie du code Inutile que j'ai vu au travail. Mais toutes ces 4 raisons supposent un programmeur intelligent. Certains codes inutiles proviennent de quelqu'un qui ne comprend pas ce qui doit se passer, et ce qui ne le fait pas, et laisse beaucoup de code purement par peur de changer ce qui fonctionne.
Bruce Ediger
2
J'ai vu # 4 dans mon projet: souvent ce n'est pas fait exprès pour avoir plus de pouvoir dans l'entreprise, mais il y a des gens qui essaient toujours de créer une solution plus générale, même si ce n'est pas nécessaire. Concernant # 2, je l’utilise beaucoup moi-même pour exactement les raisons que vous avez expliquées: même la plus petite fonction ou méthode, à mon humble avis, ne devrait pas présumer de la façon dont le reste du code fonctionne ou va changer. Au lieu de cela, mon code suit le modèle simple: "si entrée OK, alors sortie sinon erreur". Ceci suit le principe de conception général de minimisation des dépendances.
Giorgio
3
Vous avez également oublié: les mauvais développeurs. Certaines personnes qui écrivent du code ne devraient pas l'être, et les bons processus de révision n'existent pas dans de nombreux magasins.
Joe
20

Ma question est. Est-ce que quelqu'un d'autre a vu un code comme celui-ci? Quelle était votre conclusion était pourquoi ce code était là?

1) oui

2) Dans les cas que j'ai vus, je le rédigerais de différentes manières:

  • Inexpérience de programmeur
  • Le programmeur ne comprend pas un dessin particulièrement compliqué et / ou mal exécuté qu'il tente de modifier
  • Le programmateur est interrompu au milieu d'un refactor.
  • Négligence

Maintenant, peut-être que je suis charitable à ce sujet, mais mon approche générale est qu'il vaut mieux pardonner / ne pas être conflictuel à propos de ces choses-là, que de pointer du doigt et de continuer au sujet de la mauvaise qualité. De toute évidence, les choses pourraient devenir suffisamment pénibles pour que quelque chose soit fait , mais un léger coup de pouce dans la bonne direction est généralement suffisant.

Bien sûr, vous ne pouvez pas adopter une telle approche de laisser-faire si la qualité / les erreurs vont sérieusement affecter "l'entreprise". Mais dans cette situation, vous avez besoin de tout et de toutes les révisions du code obligatoires et diligentes , associées à une procédure de test complète.


D'après mon expérience, les gens ont tendance à se montrer "sévères" à propos d'un code de mauvaise qualité (au moins en partie), car cela va à l'encontre de leurs normes personnelles. C'est très bien d'essayer (personnellement) d'atteindre la perfection, mais il est un peu déraisonnable de projeter vos normes personnelles sur d'autres personnes. Par le son des choses (par exemple, d'après la nature de vos exemples), c'est ce que vous faites.

OMI, cela n’est pas productif et ne favorise pas une bonne relation de travail avec vos collègues.

Stephen C
la source
+1 Dactylographiait une réponse et vous avez trouvé à peu près toutes les raisons que j'allais mentionner.
canadiancreed
+1 pour être charitable. Corrigez les erreurs de quelqu'un sans se montrer du doigt et vos collègues respecteront à la fois vos compétences techniques et vos relations interpersonnelles. Harangue l’auteur pour son code de merde et vos collègues vous en voudront de votre approche et vous escroqueront.
Caleb
13

Tous ces éléments sont souvent des symptômes du vieillissement d'un projet.

 1. Appels de méthode ou de fonction qui n’ont aucune valeur. Il arrive souvent que du code soit laissé tel quel (avec un gros avertissement déconseillé , espérons-le , mais comme la plupart des langues ne le prévoient pas, il n'est pas toujours suivi ...) car, à un moment donné, but réel et personne ne savait ce qui pourrait arriver si les lignes incriminées étaient supprimées.

Je semble me souvenir de cela d'un dailywtf:

@deprecated // he might have been crazy enough to use reflection...
boolean getTrue() {
    return false; 
}

 2. Contrôles redondants effectués dans un fichier de classe, un objet ou une méthode distinct (e). Les couches de communication sont également imparfaites (jamais lu le Mois de l'homme mythique? Sinon, que faites-vous sur l'ordinateur !? Allez! LISEZ!). Souvent, une personne travaille sur quelque chose et quitte ensuite le projet, puis le gars suivant, à la recherche d'un bogue étrange, lance une vérification supplémentaire ici et là pour tenter de l'éliminer. Lorsque le bogue est supprimé, les vérifications ne le sont pas, eh bien, s'il n'est pas cassé, ne le corrigez pas.

 3. si les déclarations qui évaluent toujours à vrai. Oh, j'ai fait celui-ci. J'ai eu un projet une fois, il avait probablement une série de 10-15 blocs si / sinon . Pour changer le comportement, je mets simplement un true||au premier bloc. Ce n'est que des mois (des années?) Plus tard que je suis revenu et j'ai dit: "Oh, wow, ce code était censé avoir été détruit mais ne l'a jamais été"

 4. Des fils qui se détachent et ne font rien d’important. Je peux imaginer une ligne de pensée comme celle-ci:

  1. Je sais! Je peux gérer ces deux problèmes de manière asyncrone! Je vais créer des discussions foo et bar.
  2. (deux mois plus tard) Tu sais, les fonctionnalités du bar sont un peu meilleures dans foo. Je vais en déplacer plus.
  3. (un an plus tard) Vous savez, mettre ces autres choses de bar en foo a du sens.
  4. (plusieurs années plus tard) "Hé, ce barfil n'a pas l'air de faire quoi que ce soit, pouvons-nous l'enlever?" "Mieux vaut ne pas y aller, ça fait plusieurs années ..."
Cwallenpoole
la source
5
+1 pour "Mieux vaut pas, ça fait là, beaucoup d'années ..." - cela se produit encore et encore. Peur de partir par crainte des conséquences ("Comment pouvons-nous vérifier que nous n’avons pas cassé quelque chose" - surtout s’il n’ya pas de tests unitaires dans le coin).
Rapidement maintenant
11

Je suis un peu plus optimiste. Je pense que ce que vous avez décrit se produit souvent lorsque le code est refactored négligemment.

Jonathan Khoo
la source
13
Bien que ce soit difficile, n'attribuez jamais à Malice ce qui peut s'expliquer par la stupidité.
Bruce Ediger
8

Les vieux camarades me parlaient d'une époque où les consultants étaient payés en fonction du nombre de lignes de code qu'ils produisaient. Ils ont donc maximisé leurs profits en utilisant des constructions incroyablement longues.

De nos jours, je suppose toujours que le gars est encore en train d'apprendre la langue tout en faisant le travail. Et il est pressé.

ZJR
la source
Parlez de couper votre nez pour contrarier votre visage. Je suppose que ça va si vous ne devez plus jamais regarder le code.
JeffO
6

La plupart des réponses se résument à ces deux faits simples:
[1] Code reflète l'historique du code, et
[2] Code reflète l'avenir attendu du code.

J'ai écrit des fonctions qui ne font rien de précieux, DANS LE CONTEXTE D'APPLICATION ACTUEL compte tenu des SPÉCIFICATIONS ACTUELLES, mais qui pourraient s'avérer nécessaires à l'avenir.

J'ai écrit des déclarations if qui, à l'heure actuelle, sont toujours considérées comme vraies. Mais peut-être que dans le passé, cela pourrait être faux.

En ce qui concerne les chèques redondants, hé, je ne fais pas confiance à un autre code, je ne fais même pas confiance à mon propre code. Si un module dépend de N étant égal à 1, 2 ou 3, il est bien mieux de s'en assurer, et de planter de manière informelle si ce n'est pas le cas. Il est illégal que le module B explose parce que le module A a échoué; il est tout à fait légitime que le module B se plaint que le module A se soit trompé. Et rappelez-vous que, le mois prochain, ce paramètre proviendra peut-être du module C non encore écrit.

Andy Canfield
la source
1
J'appelle ça du mauvais codage. Vous vous attendez à en avoir besoin dans le futur, mais cela se produit rarement. YAGNI. Écrire un si qui est toujours considéré comme vrai est un effort inutile et une source de confusion pour la personne qui doit ajouter des fonctionnalités très probablement différentes. Ce paramètre qui arrive le mois prochain peut attendre que le mois prochain soit ajouté. Le code encombrant est maintenant inutile.
Andy
1
if (language = 'en' ou language = th ') - peut-être que nous essayerons le chinois le mois prochain? if (! isset ($ TITLE)) - tous les modules sont censés définir $ TITLE, mais peut-être qu'un jour le dira mal. if (file_exists ($ TARGET)) - un bon code aura déjà créé le fichier, mais il y a peut-être une erreur système qui n'a pas été créée. Mon code d'interface PHP / MySQL standard vérifie toujours les erreurs, même si je ne les ai pas encore détectées.
Andy Canfield
3

Je l'ai vu à quelques reprises, en fait hier encore, je dois fusionner du code de mes chefs dans ma nouvelle application. Dans son cas, il s'agit simplement d'un manque général de compétences et de compréhension et de la conviction qu'il pense être un développeur assez compétent.

"Appels de méthode ou de fonction qui ne font rien de valeur." et 'si les déclarations qui sont toujours considérées comme vraies' constituent un problème majeur pour son code.

DBlackborough
la source
3

Je soupçonne que bien que beaucoup aient vu le code contenant ces problèmes, peu de gens seraient prêts à écrire de la même manière. Selon toute vraisemblance, ce que vous voyez est une pourriture logicielle accumulée - quelqu'un ajoute quelque chose, ce qui ne fonctionne pas vraiment, le prochain responsable ajoute un code de protection plus loin dans la chaîne pour se prémunir contre la condition qui n'a pas été correctement vérifiée la première fois. endroit; alors quelqu'un reçoit un rapport de problème et ajoute encore plus d'armure contre une instance spécifique d'un problème; une autre personne ajoute une vérification plus générale et oublie de supprimer une partie de l'ancien code ajouté précédemment, qui traitait de symptômes plus spécifiques, etc.

Ensuite, il y a le problème du nettoyage du code: il n'y a aucune incitation particulière à supprimer ce qui semble être du code mort, et une incitation énorme à ne pas le faire, car si vous ne comprenez pas le code complètement, votre évaluation du fait que le code est "mort" le fera. être défectueux, et vous finirez par briser le système.

Scott C Wilson
la source
2
  • Appels de méthode ou de fonction qui ne font rien de valeur.

Pas forcément mauvais. Les méthodes d'une classe de base appellent souvent des méthodes vides désignées comme points de substitution pour les sous-classes. Exemple: UIView de Cocoa Touch a une -didAddSubview:méthode documentée comme ne faisant rien dans la version par défaut. La -addSubview:méthode UIView doit appeler -didAddSubview:même si elle ne fait rien car les sous-classes peuvent l'implémenter pour faire quelque chose. Les méthodes qui ne font rien et les raisons qui les motivent devraient bien sûr être documentées.

Si une fonction / méthode vide ou inutile est évidemment présente pour des raisons historiques, elle doit être supprimée. Jetez un coup d'œil aux versions précédentes du code de votre référentiel de code source si vous n'êtes pas sûr.

  • Contrôles redondants effectués dans un fichier de classe, un objet ou une méthode distinct (e).

Difficile à dire si ça va sans contexte. Si les vérifications sont clairement effectuées pour la même raison, cela peut signifier qu'il n'y a pas de séparation claire des responsabilités et qu'il faut procéder à une refactorisation, en particulier lorsque les deux vérifications aboutissent à la même action. Si l'action résultant des deux vérifications n'est pas la même, les deux vérifications sont probablement effectuées pour des raisons différentes, même si la condition est la même, et c'est probablement correct.

  • si les déclarations sont toujours considérées comme vraies.

Il y a une grande différence entre:

if (1) {
    // ...
}

et:

if (foo() == true) {
    // ...
}

foo()il arrive de toujours revenir true.

Le premier cas se produit souvent lorsque les personnes sont en train de déboguer. Il est facile d'utiliser un if (0) {...pour supprimer temporairement un morceau de code lorsque vous essayez d'isoler un bogue, puis changez le 0en 1pour restaurer ce code. Le ifdoit être retiré une fois que vous avez terminé, bien sûr, mais il est facile d'oublier cette étape, ou de manquer un ou deux si vous l' avez fait en plusieurs endroits. (C’est une bonne idée d’identifier de telles conditions avec un commentaire que vous pourrez ensuite rechercher.) Le seul inconvénient est la confusion que cela pourrait causer à l’avenir; si le compilateur peut déterminer la valeur de la condition au moment de la compilation, il la supprimera entièrement.

Le deuxième cas peut être acceptable. Si la condition représentée par foo()doit être testée à plusieurs endroits dans le code, son intégration dans une fonction ou une méthode distincte est souvent la bonne chose à faire, même si elle foo()s'avère toujours vraie en ce moment. S'il est concevable que cela foo()puisse éventuellement revenir false, isoler cette condition dans une méthode ou une fonction est un moyen d'identifier tous les endroits où le code s'appuie sur cette condition. Cependant , cela crée un risque que la foo() == falsecondition ne soit pas testée et puisse entraîner des problèmes plus tard; La solution consiste à ajouter des tests unitaires qui testent explicitement le falsecas.

  • Des fils qui se détachent et ne font rien d’important.

Cela ressemble à un artefact de l’historique et pourrait être identifié lors d’une révision du code ou lors du profilage périodique du logiciel. Je suppose que cela pourrait être créé intentionnellement, mais j’ai du mal à imaginer que quelqu'un le fasse volontairement.

Caleb
la source
1

Ça arrive. Assez souvent en fait.

Parfois, ces impasses de codage ressemblent davantage à de vieilles pistes de chèvre qui se sont détériorées lorsqu'un autoroute plus efficace / moderne / plus rapide a été installée autour d'eux.

En d’autres occasions (et j’en suis probablement coupable), elles constituent les fondements de l’extension du logiciel lorsqu’un ensemble de fonctionnalités / fonctions documentées, mais non confirmées, est requis. (Parfois, mettre un peu de travail dans la construction initiale en fournissant des poignées et similaires pour un travail ultérieur que vous envisagez de «verrouiller» peut rendre la vie plus facile, quand cela se produit, ou plus difficile / compliqué si le travail à venir ne fonctionne pas. eventuate.)

Et, en grande partie, cela est directement dû au vieux "Si ce n’est pas cassé, ne le va pas." Parfois, déchirer du code que vous ne comprenez pas, ou croyez inutilisé, peut provoquer la version de programmation de "L’effet papillon". Cela s'est déjà produit une ou deux fois.

Luke Stevenson
la source
1

Parfois, un booléen global est défini sur true, et plus tard dans mon code, un if (bool), puis pendant l'exécution, je pourrais définir un point d'arrêt à l'instruction if et basculer le booléen pour tester quelque chose.

Patrick
la source
0

Je m'oppose à ce que les if truedéclarations soient classées indifféremment comme "code inutile".

Il est tout à fait légitime d’utiliser un if (1) { ... }bloc de code C qui soit veut être compatible avec le standard C qui insiste sur le fait que les définitions de variable doivent figurer au début d’une fonction, ou veut simplement que les variables locales soient définies aussi localement que possible.

switch (i) {
    case 23:
        if (1) {
            /* I can declare a local var here! */
        }
        break;
}
ndim
la source
5
Le 'si (1)' n'est pas nécessaire, pourquoi ne pas simplement avoir le bloc?
FigBug
3
C / C ++ et C #, et je suis à peu près sûr que Java (ainsi que de nombreux autres langages similaires) autorise les blocs d'instructions anonymes; pas besoin d'une construction if, whileou similaire. Il est peu probable que ce soit très propre, mais cela est certainement autorisé en fonction des spécifications linguistiques.
un CVn
0

Un de mes professeurs nous a raconté un jour l’histoire qu’un ancien employeur leur paierait en fonction du nombre de lignes qu’il avait complétées. Ils ont donc écrit plusieurs dizaines de fonctions alignées qui n’ont jamais été appelées. Cela semble être une bonne raison pour écrire du code inutile.

Casey
la source
0

Comme @Andy l'a mentionné, un composant important que j'ai vu est la rupture de YAGNI .

Quelqu'un commence par une hypothèse sur ce que tous les éléments seront au lieu de ce dont beaucoup d'éléments peuvent avoir besoin , ce qui est une confusion des relations "est un" et "a" .

Cette confusion conduit à une structure d'héritage rigide. Ce sont des méthodes qui ne sont pas implémentées car elles ne sont jamais appelées, une logique répétée dans laquelle des portions doivent être modifiées et des flux de travail généralement étranges qui ne sont pas alignés sur le modèle commercial.

Comme beaucoup d’autres ici, je n’ai pas vu cela se faire de manière malveillante, mais par manque de connaissances sur la conception de qualité et sur la tentative de le rendre ainsi aux autres. Drôle, il semble que les développeurs, même les moins informés, semblent faire mieux à cet égard, car au moins leur code ne finit pas par être trop conçu ad naseum. ( Principe du baiser )

MaxWell
la source