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?
if (false) {...}
les blocs sont parfaits pour commenter le code! </Réponses:
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.
la source
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:
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.
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?
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.
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.
la source
1) oui
2) Dans les cas que j'ai vus, je le rédigerais de différentes manières:
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.
la source
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:
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:
bar
fil 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 ..."la source
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.
la source
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é.
la source
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.
la source
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.
la source
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.
la source
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.
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.
Il y a une grande différence entre:
et:
où
foo()
il arrive de toujours revenirtrue
.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 le0
en1
pour restaurer ce code. Leif
doit ê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 ellefoo()
s'avère toujours vraie en ce moment. S'il est concevable que celafoo()
puisse éventuellement revenirfalse
, 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 lafoo() == false
condition ne soit pas testée et puisse entraîner des problèmes plus tard; La solution consiste à ajouter des tests unitaires qui testent explicitement lefalse
cas.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.
la source
Ç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.
la source
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.
la source
Je m'oppose à ce que les
if true
dé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.la source
if
,while
ou similaire. Il est peu probable que ce soit très propre, mais cela est certainement autorisé en fonction des spécifications linguistiques.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.
la source
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 )
la source