Quelles sont les choses qui déclenchent instantanément l'alarme lorsque vous regardez un code? [fermé]

98

J'ai assisté à un événement sur la conception de logiciels il y a quelques semaines et l'un des commentaires formulés était: "Je suis sûr que nous reconnaissons tous le code défectueux quand nous le voyons" et tout le monde a acquiescé avec honte sans autre discussion.

Ce genre de chose m'inquiète toujours car il y a ce truisme que tout le monde pense être un conducteur supérieur à la moyenne. Bien que je pense pouvoir reconnaître le mauvais code, j'aimerais en savoir plus sur ce que les autres utilisateurs considèrent comme des odeurs de code, car il est rarement discuté en détail sur les blogs des internautes et seulement dans une poignée de livres. En particulier, je pense qu'il serait intéressant d'entendre parler de tout ce qui ressemble à une odeur de code dans une langue mais pas une autre.

Je vais commencer par un facile:

Code dans le contrôle de source qui contient une forte proportion de code commenté - pourquoi est-il là? Était-ce censé être supprimé? est-ce un travail à moitié fini? peut-être n'aurait-il pas dû être commenté et n'a été fait que lorsque quelqu'un testait quelque chose? Personnellement, je trouve ce genre de chose vraiment ennuyeux, même s’il s’agit d’une simple ligne ici et là, mais il est totalement inacceptable de voir de gros blocs entremêlés du reste du code. Cela indique aussi généralement que le reste du code sera probablement de qualité douteuse.

FinnNk
la source
61
Je rencontre parfois des gens qui commentent le code, enregistrent et disent "J'en aurai peut-être besoin à l'avenir - si je le supprime maintenant, je le perdrai". Je dois contrer avec "Euh ... mais c'est à quoi sert le contrôle de source".
Talonx
6
Parfois, en particulier lors de l’optimisation, il est pratique de laisser l’ancien code sous forme de commentaire afin de savoir ce que le code optimisé et obscur remplace. Pensez à laisser un échange à 3 lignes avec temp en place lorsque vous le remplacez par un échange à une ligne. (Bien que, je ne vois pas la nécessité d'utiliser un échange d'une ligne - JAMAIS, sauf si la taille du programme est d'une importance capitale.)
Chris Cudmore
4
Je maintiens / nettoie le code écrit par l'un de nos ingénieurs, qui a codé des choses utiles mais reconnaît qu'il n'est pas un programmeur. Au fur et à mesure que je consolide les éléments, je commente son ancien code, puis nous examinons les modifications et je lui montre comment je l'ai remplacé par quelque chose de plus petit / plus efficace / plus facile à comprendre. Ensuite, je supprime ces blocs puis je vérifie. L’ancien code présente des avantages, car il voit comment on peut faire les choses plus simplement et je me souviens bien pourquoi j’ai changé les choses lorsque nous parlons.
Le Tin Man
8
Je laisse des éléments qui "pourraient être utilisés" dans 1 commit, puis si les choses ne tombent pas en panne ou si un besoin n’est pas trouvé, il est supprimé lors du prochain commit.
Paul Nathan
24
Hmm. printf("%c", 7)sonne typiquement des cloches d’alarme pour moi. ;)

Réponses:

128
/* Fuck this error */

Généralement trouvé dans un try..catchbloc absurde , il a tendance à attirer mon attention. À peu près aussi bien que /* Not sure what this does, but removing it breaks the build */.

Quelques autres choses:

  • Plusieurs ifdéclarations complexes imbriquées
  • Blocs try-catch utilisés pour déterminer régulièrement un flux logique
  • Fonctions avec des noms génériques process, data, change, rework,modify
  • Six ou sept styles de contreventement différents sur 100 lignes

Un que je viens de trouver:

/* Stupid database */
$conn = null;
while(!$conn) {
    $conn = mysql_connect("localhost", "root", "[pass removed]");
}
/* Finally! */
echo("Connected successfully.");

Oui, car le fait de forcer brutalement vos connexions MySQL est la bonne façon de faire les choses. Il s'est avéré que la base de données avait des problèmes avec le nombre de connexions, elle a donc continué à expirer. Au lieu de déboguer cela, ils ont simplement essayé encore et encore jusqu'à ce que cela fonctionne.

Josh K
la source
19
Si seulement je pouvais voter 6 fois! Tous les bons exemples. Je n'aime pas non plus les commentaires arrogants / amusants (surtout s’ils incluent les jurons) - cela peut sembler un peu amusant la première fois que vous les lisez, mais vous devenez très vieux (et donc distrayant) très rapidement.
FinnNk
5
J'aime votre exemple, même si je dirais que dans certains contextes, plusieurs déclarations imbriquées sont inévitables. Avec beaucoup de logique métier, le code peut être un peu déroutant, mais si l’entreprise elle-même est source de confusion au début, simplifier le code reviendrait à modéliser le processus de manière moins précise. Comme le disait Einstein: "Les choses doivent être aussi simples que possible et pas un peu plus simples."
Morgan Herlocker
2
@Prof Plum - Quel exemple pouvez-vous donner? Habituellement, l'alternative à plusieurs imbriqués est de le diviser en (plusieurs) méthodes. Les développeurs débutants ont tendance à éviter cela comme si c'était moins souhaitable que les ifs; mais en général, quand ils sont pressés, ils disent "si c'est fait en moins de lignes". Il faut quelqu'un de confiance en OOP pour intervenir et leur rappeler que moins de lignes! = Meilleur code.
STW
2
@STW C'est un bon point, cependant, je dirais que cela dépend de la profondeur de la nidification. Je conviens certainement que tout ce qui dépasse trois nids de profondeur nécessite souvent une refactorisation, car il va devenir très poilu. Les citations d’assurance sont cependant un bon exemple où la nidification multiple peut très bien modéliser le monde réel. Avec des exceptions à certains taux / primes, le manuel indiquera littéralement quelque chose du type "s’il s’agit d’une propriété et si elle a un taux minimum inférieur à 5,6 et si elle est en NC et si elle a un bateau sur les lieux, alors tel." avec beaucoup d'autres options.
Morgan Herlocker
4
@ josh, si "ils" sont des collègues, je me demanderais pourquoi vous n'avez pas dit "nous" ...
104

Le principal drapeau rouge pour moi est le double des blocs de code, car il montre que la personne ne comprend pas les bases de la programmation ou a trop peur pour apporter les modifications appropriées à une base de code existante.

J'avais aussi l'habitude de compter le manque de commentaires comme un drapeau rouge, mais comme j'ai récemment travaillé sur beaucoup de très bons codes sans commentaires, je suis revenu à cette question.

Ben Hughes
la source
1
+1: J'ai vu du code d'un collègue qui se vantait d'être un expert de Linux, qui a écrit une simple application en boucle comme une fonction longue, le tout encore et encore dans main (). Beurk.
KFro
4
@KFro, c'est la boucle qui se déroule. C’est ce que les compilateurs font tout le temps :) TRÈS efficace!
3
@Thorbjorn: Parfois, vous devez aider un peu le compilateur; après tout, vous êtes un humain intelligent et il n’est qu’un ordinateur stupide.
Yatima2975
3
Une autre raison que j’ai vue: le consultant a été payé pour mettre en œuvre la fonctionnalité le plus rapidement possible (c’est pourquoi les tests et la documentation manquent aussi, bien sûr). Copier / coller est plus rapide que de réfléchir à la manière de bien faire les choses.
LennyProgrammers
4
Éviter la duplication de code peut être une obsession. Dans un langage tel que C ++, il n'est pas toujours aussi facile qu'il devrait l'être de décomposer les différentes parties tout en conservant un code robuste et efficace. Parfois, un peu de couper-coller est l’option la plus pratique. En outre, le principe d'optimisation peut s'appliquer - couper-coller peut vous fournir une solution simple et rapide que vous pourrez refactoriser ultérieurement si nécessaire. Vous économiserez peut- être un mal de tête pour plus tard, mais vous savez avec certitude que vous évitez les retards en ce moment.
Steve314
74

Code qui tente de montrer l’intelligence du programmeur, même s’il n’ajoute aucune valeur réelle:

x ^= y ^= x ^= y;
Rei Miyasaka
la source
12
Wow, c'est tellement beaucoup plus lisible queswap(x, y);
JBRWilkinson
8
si x et y sont des pointeurs et que cette affectation a lieu sur un laps de temps raisonnable, elle casse les éboueurs conservateurs tels que Boehm GC.
SingleNegationElimination
12
À propos, ce code n’a pas été défini en C et C ++ à cause de multiples modifications sans point de séquence intermédiaire.
fredoverflow
9
En regardant cela, la seule chose qui me vint à l'esprit fut les émoticônes:^_^
Darien
62
  • 20 000 fonctions de ligne (exagérées). Toute fonction nécessitant plus que quelques écrans nécessite une refactorisation.

  • Dans le même ordre d'idées, les fichiers de classe qui semblent durer éternellement. Il existe probablement quelques concepts que l'on pourrait résumer en classes afin de clarifier le but et la fonction de la classe d'origine, et probablement leur utilisation, à moins qu'il s'agisse de méthodes internes.

  • variables non descriptives, non triviales, ou trop nombreuses variables non descriptives triviales. Celles-ci font de ce qui se passe réellement une énigme.

Dominique McDonnell
la source
9
J'ai tendance à limiter les fonctions à 1 écran autant que possible.
Matt DiTrolio
20
1 écran est même un étirement. Je commence à me sentir sale après une dizaine de lignes.
Bryan Rowe
54
D'accord, je vais exprimer ce qui peut être une opinion impopulaire. Je dis que c’est une odeur de code pour écrire des fonctions atomiques, des processus de haut en bas qui sont divisés en fonctions séparées parce que le développeur s’accroche à certaines "fonctions devraient être courtes", au service du développement des cargaisons. Les fonctions doivent être réparties le long des lignes FONCTIONNELLES, pas seulement parce qu’elles doivent être mythiques. C'est pourquoi ils s'appellent FONCTIONS.
Dan Ray
7
@Dan, les fonctions ne doivent pas être courtes pour ne pas être brèves, mais vous ne pouvez garder que trop d’informations à la fois. J'ai peut-être un petit cerveau car pour moi cette limite est de quelques écrans :). Diviser les fonctions en plusieurs fonctions quand ils commencent à tester cette limite est nécessaire pour éviter les erreurs. D'une part, il offre une encapsulation pour que vous puissiez penser à un niveau supérieur et, d'autre part, il cache ce qui se passe, il est donc plus difficile de comprendre le fonctionnement de la fonction. Je pense que la séparation des fonctions devrait être faite pour améliorer la lisibilité, et non pour correspondre à une «longueur parfaite».
Dominique McDonnell
6
@ Dominic, @ Péter, je pense que nous disons tous les trois la même chose. Quand il y a une bonne raison de factoriser le code dans une fonction plus petite, je suis pour. Ce que je rejette, c’est la brièveté par souci de brièveté dans la conception des fonctions. Vous savez, une pile d'appels est trois fois plus longue que nécessaire, mais au moins ces fonctions sont courtes. Je préférerais déboguer une fonction haute qui fait une chose clairement et bien que de poursuivre le chemin d'exécution à travers une douzaine de fonctions chaînées appelées chacune depuis la précédente.
Dan Ray
61
{ Let it Leak, people have good enough computers to cope these days }

Le pire, c'est que ça vient d'une bibliothèque commerciale!

Vraiment éthiques
la source
32
Cela ne sonne pas la sonnette d'alarme. Il vous frappe pratiquement entre les jambes.
Steven Evers
15
Fille est un toxicomane à la méthamphétamine. Peu importe, au moins elle ne deviendra pas obèse. :: soupir ::
Evan Plaice
17
Quand je me trouve dans des moments difficiles, la mère Buntu vient à moi. En prononçant des mots de sagesse, laissez-le couler LAISSEZ LA FUITE .. LAISSONS LA FUITE. LAISSEZ LA FUITE oh LAISSEZ LA FUITE. Si cela ne fuit qu'une fois, ce n'est pas un leaaaaaak. (si vous lisez jusque là, +1). J'ai vraiment besoin de considérer décaféiné.
Tim Post
13
"Alors que la date limite approche, les fuites sont tout ce que je peux voir, quelque part, quelqu'un chuchote: 'Ecrivez en C ...... eeeeee !!!'"
chiurox
9
Il était une fois deux systèmes d'exploitation. L’une fuyait et s’écroulait si elle fonctionnait plus de 49 jours, l’autre était parfaite et fonctionnerait à jamais. L’une a été lancée en 1995 dans un grand public et a été utilisée par des millions de personnes - l’autre n’a jamais été expédiée car elle vérifie toujours qu’elle est exempte de bogues. Il y a une différence entre philosophie et ingénierie.
Martin Beckett
53

Les commentaires si verbeux que s'il y avait un compilateur anglais, celui-ci serait parfaitement compilé et parfaitement exécuté, sans toutefois décrire le code.

//Copy the value of y to temp.
temp = y;
//Copy the value of x to y.
y = x;
//Copy the value of temp to x.
x = temp;

En outre, les commentaires sur le code qui auraient pu être supprimés s’ils avaient été respectés:

//Set the age of the user to 13.
a = 13;
Rei Miyasaka
la source
15
Voilà, ça s'appelle COBOL :-)
Gaius
26
Le deuxième cas n'est pas le pire. Le pire est: / * Définissez l’âge de l’utilisateur sur 13 * / a = 18;
PhiLho
4
@PhiLho - non, c'est encore pire quand le /de */est manquant, donc tout le code à la fin de la prochaine */est ignoré. Heureusement, la coloration syntaxique rend ce genre de chose rare de nos jours.
Steve314
3
Pire encore, apour user_age? Vraiment?
Glasnt
2
Auparavant, je conservais chez un employeur précédent un document normalisé en code, dont l'une des sections était commentée. Mon exemple préféré était de MSDN:i = i + 1; //increment i
Michael Itzoe
42

Code qui produit des avertissements lors de la compilation.

Rei Miyasaka
la source
1
Il y a un candidat pour ajouter l'option du compilateur 'Tous les avertissements en tant qu'erreurs' au makefile / project.
JBRWilkinson
3
Je suppose que cela pourrait être utile si vous êtes dans un projet avec plusieurs personnes en qui vous n’avez simplement pas confiance - bien que si je devais rejoindre un projet dans lequel cette option est définie, cela me priverait en moi de la capacité de l’autre les programmeurs sont.
Rei Miyasaka
1
Je ne suis pas d'accord avec ça. Certains avertissements du compilateur (tels que la comparaison entre signés et non signés, lorsque vous savez que les deux valeurs ne sont pas signées, même si les types sont différents) sont préférables à la juxtaposition de code avec des conversions inutiles. Si je réduis le code en utilisant un entier signé portable qu'une fonction ne modifie que si l'entier a une valeur non signée, je vais le faire.
Tim Post
13
Je préférerais encombrer mon code avec un contenu presque superflu (unsigned int)que d’encombrer mes listes d’avertissements / erreurs avec des avertissements bénins. Je détesterais que la liste d'avertissement devienne un angle mort. Il est aussi beaucoup plus d'un PITA expliquer à d' autres personnes pour lesquelles vous ne tenez pas compte d' un avertissement que d'expliquer pourquoi vous faites un casting de naturel intsà unsigned ints.
Rei Miyasaka
De temps en temps, vous devez utiliser une API qui génère des erreurs quoi que vous fassiez. Les exemples classiques sont ceux où l’API est définie en termes d’objets brisés par la conception (de vieilles constantes ioctl () étaient comme ça, et parfois les développeurs d’OS insistent pour utiliser le mauvais type dans leurs en-têtes) ou pour lesquels ils ont déconseillé quelque chose sans laissant un bon remplaçant (merci Apple).
Donal Fellows
36

Fonctionne avec des nombres dans le nom au lieu d'avoir des noms descriptifs , comme:

void doSomething()
{
}

void doSomething2()
{
}

Faites en sorte que les noms de fonctions aient un sens! Si doQething et doquething2 font des choses similaires, utilisez des noms de fonctions qui différencient les différences. Si doSomething2 est une rupture des fonctionnalités de doSomething, nommez-le pour ses fonctionnalités.

Wonko the Sane
la source
De même, @Parm for SQL
Dave
2
+1 - Entrez mshtml- ça me brise les yeux :(
Kyle Rozendo
3
L'exception à cette règle serait le code d'interface graphique. Par exemple, si un formulaire de courrier postal avait deux adresses; address1 and address2 est plus raisonnable que address et alternateAddress. Les étiquettes parasites uniquement statiques constituent également une exception raisonnable.
Evan Plaice
@ Evan - assez bien, même si je faisais une distinction dans la fonctionnalité.
Wonko the Sane le
1
+1 - J'ai même vu cela utilisé comme méthode de contrôle de pseudo-version.
EZ Hart
36

Chiffres magiques ou cordes magiques.

   if (accountBalance>200) { sendInvoice(...); }

   salesPrice *= 0.9;   //apply discount    

   if (invoiceStatus=="Overdue") { reportToCreditAgency(); }
JohnFx
la source
4
Pas vraiment si mal avec les deux autres, au moins la réduction est expliquée, et le "En retard" est intuitif. Le 200, en revanche ...
Tarka
9
@Slokun - Intuitif n'est pas tant le problème de la maintenabilité et de la fragilité. Par exemple, considérons ce qui se produit lorsque le montant de la remise change et que la 0.9 est codée en dur à six endroits différents. En outre, l'utilisation de chaînes au lieu de constantes / enums pose des problèmes dans les langues avec des chaînes sensibles à la casse.
JohnFx
+1 Je viens de passer beaucoup trop de temps à déboguer un problème qui s'est avéré être causé par une ligne 'timeout = 15;' enterré dans un programme.
aubreyrhodes
Je pense que le dernier est parfois correct, en fonction de l’origine des données de factureStatus. Si cela vient simplement d'une API publique qui renvoie un JSON qui vient d'être décodé, il est probablement correct de vérifier une constante de chaîne codée en dur. Convenez bien que "200" et "0,9" ne sont que des constantes magiques et ne devraient pas être codés en dur de cette façon. Même s'ils ne sont utilisés que dans cet emplacement, la maintenance est plus facile si vous les définissez séparément dans une section de configuration plutôt que de les intercaler dans le code logique. Et s’ils sont utilisés à plusieurs endroits, la maintenance devient beaucoup plus facile.
Ben Lee
36
  • Peut-être pas le pire mais montre clairement le niveau des développeurs:

    if(something == true) 
  • Si un langage a une construction for loop ou iterator, utiliser une boucle while montre également le niveau de compréhension du langage des développeurs

    count = 0; 
    while(count < items.size()){
       do stuff
       count ++; 
    }
    
    for(i = 0; i < items.size(); i++){
      do stuff 
    }
    //Sure this is not terrible but use the language the way it was meant to be used.
    
  • Une mauvaise orthographe / grammaire dans la documentation / commentaires me ronge presque autant que le code lui-même. La raison en est que le code était destiné aux humains à lire et aux machines à fonctionner. C’est la raison pour laquelle nous utilisons des langages de haut niveau. Si votre documentation est difficile à maîtriser, j’ai un avis négatif sur la base de code sans la regarder.

Chris
la source
29

Celui que je remarque immédiatement est la fréquence des blocs de code profondément imbriqués (if, while, etc). Si le code a souvent plus de deux ou trois niveaux de profondeur, c'est le signe d'un problème de conception / logique. Et s’il a une profondeur de 8 nids, il vaut mieux une bonne raison de ne pas le briser.

Grand maître b
la source
6
Je sais que certaines personnes ont appris que chaque méthode ne devrait comporter qu'un seul returnénoncé, mais quand elle provoque plus de 6 niveaux d'imbrication si / alors, je pense que cela fait plus de mal que de bien.
Darien
28

Lors de la notation du programme d'un étudiant, je peux parfois dire en un clin d'œil. Ce sont les indices instantanés:

  • Formatage médiocre ou incohérent
  • Plus de deux lignes vides dans une rangée
  • Conventions de dénomination non standard ou incohérentes
  • Code répété, plus les répétitions sont textuelles, plus l'avertissement est puissant
  • Ce qui devrait être un simple morceau de code est excessivement compliqué (par exemple, vérifier les arguments passés à main de manière compliquée)

Mes premières impressions sont rarement incorrectes et ces sonneries d’avertissement ont raison environ 95% du temps . À une exception près, un étudiant débutant dans la langue utilisait un style provenant d'un autre langage de programmation. Le fait de creuser et de relire leur style dans le langage de l’autre langue a permis de sonner l’alarme, et l’élève a eu tout le crédit qu’il méritait. Mais de telles exceptions sont rares.

Lorsque vous envisagez un code plus avancé, voici mes autres avertissements:

  • La présence de nombreuses classes Java qui ne sont que des "structures" pour contenir des données. Peu importe que les champs soient publics ou privés et utilisent des accesseurs, cela ne fait toujours pas partie d'un projet bien pensé.
  • Les classes qui ont des noms pauvres, comme être juste un espace de noms et qu'il n'y a pas de réelle cohésion dans le code
  • Référence à des modèles de conception qui ne sont même pas utilisés dans le code
  • Gestionnaires d'exception vides sans explication
  • Lorsque j'extrais le code dans Eclipse, des centaines d'avertissements jaunes le délimitent, principalement à cause d'importations ou de variables inutilisées.

En termes de style, je n'aime généralement pas voir:

  • Les commentaires Javadoc qui font uniquement écho au code

Ce ne sont que des indices sur le mauvais code. Parfois, ce qui peut sembler être du mauvais code ne l'est pas vraiment, car vous ne connaissez pas les intentions du programmeur. Par exemple, il peut y avoir une bonne raison pour que quelque chose semble trop complexe - il peut y avoir eu une autre considération en jeu.

Macneil
la source
Je ne vois pas en quoi l'utilisation du style d'une langue dans une autre est une grave erreur (2, 4, 8 espaces par retrait ...). Si l'élève a peu de style à suivre, il n'y a rien de mal à rester cohérent. En tant que correcteur, vous voyez un milliard de programmes, vous êtes donc à l'extrémité opposée de ce spectre, mais ce n'est pas une raison pour écarter totalement un style différent (mais cohérent).
Nick T
18
Je ne vois rien de mal aux classes qui agrègent simplement des données - c'est-à-dire des structs. C'est ce que sont les objets de transfert de données (DTO) et peuvent rendre le code beaucoup plus lisible que par exemple, en transmettant par exemple 20 paramètres à une méthode.
Nemi
1
Votre commentaire à propos de structs est sur place. C'est bien quand les données sont dans leur forme la plus brute et ne seront en aucun cas modifiées. Mais 95% du temps, vous devriez avoir certaines fonctions dans la classe pour formater / utiliser les données. Je viens de me rappeler que certains de mes codes utilisent essentiellement ce modèle et devraient être améliorés.
DisgruntledGoat
2
+1 pour le style incohérent et les sauts de ligne supplémentaires (j'ai vu des indentations aléatoires, aucune indentation, des conventions de dénomination aléatoires et changeantes, etc. - et cela dans le code de production!). Si vous ne pouvez même pas vous donner la peine de faire les choses, alors que ne pouvez-vous pas être dérangé?
Dean Harding
1
Je cherche la ligne de déclaration d'une méthode indentée trop loin par rapport au corps. C'est un signe qu'ils ont copié-collé à partir du fichier de quelqu'un d'autre.
Barry Brown
25

Favori personnel / bête noire: Les noms générés par l'IDE ont été validés. Si TextBox1 est une variable majeure et importante dans votre système, vous avez une autre chose à venir, la révision du code.

Wyatt Barnett
la source
25

Variables totalement inutilisées , en particulier lorsque la variable porte un nom similaire aux noms de variables utilisés.

Traverser
la source
21

Beaucoup de gens ont mentionné:

//TODO: [something not implemented]

Bien que je souhaite que cela soit mis en œuvre, au moins ils ont pris une note. Ce que je pense être pire, c'est:

//TODO: [something that is already implemented]

Todo's sont sans valeur et déroutant si vous ne prenez jamais la peine de les enlever!

Morgan Herlocker
la source
1
Je viens juste de passer par l’exercice consistant à produire un rapport de tous les TODO de notre version, ainsi qu’un plan de mise au rebut. Près de la moitié s'est révélée obsolète.
AShelly
1
-1 Les commentaires TODO sont utilisés dans MS Visual Studio pour suivre les parties du projet qui ont encore besoin de travail. En d'autres termes, l'EDI conserve une liste de suivi des TODO afin que vous puissiez facilement cliquer dessus et être dirigé directement vers la ligne sur laquelle le TODO existe. Je préférerais que les TODO soient placés explicitement pour voir quel travail reste à faire. Voir dotnetperls.com/todo .
Evan Plaice
3
@ Evan Plaice: Wow, vous voulez dire que VS IDE reconnaît quand vous avez implémenté quelque chose et supprime le //TODOcommentaire? Impressionnant!
JBRWilkinson
4
@Prof Plum Pourquoi ne pas simplement créer une politique dans laquelle la personne responsable d'un TODO inscrit son nom dans le commentaire. De cette façon, s'il y a des restes
Evan Plaice
3
Mieux vaut planifier que d’ // TODO utiliser votre traqueur de bogues, c’est la raison de son utilisation!
SingleNegationElimination
20

Une méthode qui nécessite que je fasse défiler l'écran pour tout lire.

BradB
la source
14
Hmm .. cela dépend de ce qui est mis en œuvre. Il ne serait pas déraisonnable que cela se produise lors de l’implémentation de certains algorithmes complexes, car c’est ainsi qu'ils sont définis. Bien sûr, si la majorité des méthodes sont ainsi, c'est un drapeau rouge.
Billy ONeal
9
En tant que déclaration générale, je ne suis pas d'accord, perdre du temps à refactoriser constamment afin que tout corresponde à ce genre de règle auto-imposée augmente en réalité le coût global du projet.
Type anonyme
1
Je ne pense pas que cette règle puisse augmenter le coût global d'un projet, mais j'imagine que c'est subjectif, car cela dépend du ou des développeurs. Si vous vous en tenez au principe général de la "séparation des préoccupations" tout en développant, la refactorisation serait moins une tâche si on choisissait de le faire. Il convient de se demander combien cela coûterait trois ans plus tard, lorsque les développeurs qui n’ont pas codé le projet original essaient de corriger un tas de méthodes comportant plus de 300 lignes de code? Combien ça coûte?
BradB
18
Je suis plus ennuyé de faire défiler à droite que de faire défiler vers le bas. Les espaces sont "gratuits".
Wonko the Sane
4
Je préférerais faire défiler le contenu plutôt que de le parcourir (ou plusieurs fichiers) pour comprendre ce que fait le code.
TMN
20

Conjonctions dans les noms de méthodes:

public void addEmployeeAndUpdatePayrate(...) 


public int getSalaryOrHourlyPay(int Employee) ....

Clarification: La raison pour laquelle cela sonne l'alarme est qu'elle indique que la méthode enfreint probablement le principe de responsabilité unique .

JohnFx
la source
Hmmm ... si le nom de la fonction définit avec précision ce que la fonction fait, alors je ne suis pas d'accord. Si la méthode fait deux choses distinctes qu'il serait préférable de séparer, alors je peux être d' accord, en fonction du contexte.
Wonko the Sane 25/10/10
2
C'est le but. La conjonction implique qu'il est très probable qu'il fasse plus d'une chose. Selon la question, c'est simplement quelque chose qui me fait prendre conscience que quelque chose peut être faux.
JohnFx
3
Maintenant que se passe-t-il si vous devez ajouter un employé et mettre à jour son taux de rémunération à plusieurs endroits? Si cette méthode contient deux appels de méthode ( addEmployee(); updatePayrate();), alors je ne pense pas que ce soit un problème.
Matt Grande
13

Lier évidemment le code source de GPL à un programme commercial à source fermée.

Non seulement cela crée un problème juridique immédiat, mais selon mon expérience, cela indique généralement soit une négligence ou une insouciance, ce qui est également reflété ailleurs dans le code.

Bob Murphy
la source
6
Bien que votre argument soit excellent, votre ton est inutile.
JBRWilkinson
@ JBRWilkinson: Merci, vous avez raison. Mes excuses à tous.
Bob Murphy
Je pense que votre rubrique a besoin d'être réécrite. La liaison statique et dynamique au code source de GPL est une violation de la licence GPL ...
Gavin Coates
Bons points. J'ai réécrit l'intégralité du message. Merci à tous.
Bob Murphy
9

Langue agnostique:

  • TODO: not implemented
  • int function(...) { return -1; } (identique à "non implémenté")
  • Lancer une exception pour une raison non exceptionnelle.
  • Mauvaise utilisation ou utilisation incohérente de 0, -1ou nullcomme valeurs de retour exceptionnelles.
  • Des affirmations sans commentaire convaincant expliquant pourquoi cela ne devrait jamais échouer.

Spécifique à la langue (C ++):

  • Macros C ++ en minuscule.
  • Variables statiques ou globales C ++.
  • Variables non initialisées ou non utilisées.
  • Tout ce array newqui n'est apparemment pas RAII-safe.
  • Toute utilisation d'un tableau ou d'un pointeur apparemment non contraignant. Cela comprend printf.
  • Toute utilisation de la partie non initialisée d'un tableau.

Microsoft C ++ spécifique:

  • Tous les noms d'identifiant qui entrent en conflit avec une macro déjà définie par l'un des fichiers d'en-tête Microsoft SDK.
  • En général, toute utilisation de l'API Win32 est une source importante de sonneries d'alarme. Ayez toujours MSDN ouvert et recherchez les définitions des arguments / valeurs renvoyées en cas de doute. (Édité)

Spécifique à C ++ / OOP:

  • Héritage d'implémentation (classe concrète) où la classe parente utilise des méthodes à la fois virtuelles et non virtuelles, sans distinction conceptuelle évidente entre ce qui devrait / ne devrait pas être virtuel.
rwong
la source
18
// TODO: Commentez cette réponse
johnc
8
Je suppose que "langage agnostique" signifie "C / C ++ / Java" maintenant?
Inaimathi
+1 "Lancer une exception pour une raison non exceptionnelle" ne pourrait pas être plus d'accord!
billy.bob
2
@Inaimathi - Les commentaires TODO, les stubs de fonction, les exceptions abusives, la confusion entre sémantique nulle / nulle / vide et les contrôles de cohérence inutiles sont inhérents à tous les langages impératifs / OOP et, dans une certaine mesure, à tous les langages de programmation en général.
Rei Miyasaka
Je pense que les macros du préprocesseur C en minuscule sont acceptables, mais uniquement si elles évaluent leurs arguments une seule fois et ne produisent qu'une seule instruction.
Joe D
8

Style d'indentation bizarre.

Il y a quelques styles très populaires, et les gens vont pousser ce débat dans la tombe. Mais parfois, je vois quelqu'un qui utilise un style d'indentation vraiment rare, voire développé localement. C'est un signe qu'ils n'ont probablement pas codé avec quelqu'un d'autre qu'eux-mêmes.

Ken
la source
2
ou simplement un signe qu'ils sont un talent individualiste très prisé qui ne s'est pas laissé prendre au piège du réseau de pratiques de codage homogonisées qui ne sont aucunement liées aux "meilleures pratiques".
Type anonyme
1
J'espère que tu es sarcastique. Si quelqu'un code de manière si inhabituelle, cela devrait déclencher des sonnettes d'alarme. Ils peuvent être aussi artistiques qu’ils le souhaitent, mais quand même… des sonnettes d’alarme.
Ken
2
Il y a un style quelque peu inhabituel (je crois que cela s'appelle le style d'Utrecht) qui, à mon avis, est très utile bien qu'il soit extrêmement rare en dehors de Haskell / ML / F #. Faites défiler jusqu'à "module formes": learnyouahaskell.com/making-our-own-types-and-typeclasses . Ce qui est bien avec ce style, c'est que vous n'avez pas besoin de modifier le délimiteur de la ligne précédente pour en ajouter un nouveau - ce que j'oublie souvent de le faire.
Rei Miyasaka
@ReiMiyasaka Sept ans de retard, mais ... le style d'Utrecht m'énerve vraiment. Je pense que c'est une erreur dans la spécification Haskell de ne pas imposer une autre "règle de mise en page" aux listes organisées verticalement. De cette façon, l'analyseur pourrait détecter une nouvelle entrée de liste simplement en vérifiant l'indentation, ce qui permet à tout le monde d'organiser ses listes.
Ryan Reich
@RyanReich Weird, sept ans plus tard, et je l'aime toujours. Je suis d'accord, cependant; malgré toutes ses maladresses et ses défaillances syntaxiques, F # permet également de délimiter les éléments simplement par une nouvelle ligne et une indentation (dans la plupart des cas), ce qui permet d'obtenir un code ordonné.
Rei Miyasaka
8

Utiliser beaucoup de blocs de texte plutôt que des énumérations ou des variables définies globalement.

Pas bon:

if (itemType == "Student") { ... }

Mieux:

private enum itemTypeEnum {
  Student,
  Teacher
}
if (itemType == itemTypeEnum.Student.ToString()) { ... }

Meilleur:

private itemTypeEnum itemType;
...
if (itemType == itemTypeEnum.Student) { ... }
Yaakov Ellis
la source
Ou mieux: utilisez le polymorphisme.
Lstor
8

Paramètres faiblement typés ou renvoyant des valeurs sur des méthodes.

public DataTable GetEmployees() {...}

public DateTime getHireDate(DataTable EmployeeInfo) {...}

public void FireEmployee(Object EmployeeObjectOrEmployeeID) {...}
JohnFx
la source
2
+1: Je dois travailler avec des services Web «REST» qui renvoient tout sous forme de tableaux pseudo-HTML, même lorsque vous transmettez des éléments qui constituent une erreur syntaxique évidente. Pas autorisé? Entrée complète indésirable? Serveur surchargé? 200 (plus un message dans un format horrid dans une table à une colonne, une ligne). AAaaaaaaaargh!
Donal Fellows
7
  • Plusieurs opérateurs ternaires sont liés, de sorte que, au lieu de ressembler à un if...elsebloc, il devient un if...else if...[...]...elsebloc
  • Noms de variable longs sans traits de soulignement ni camelCasing. Exemple tiré d'un code que j'ai extrait:$lesseeloginaccountservice
  • Des centaines de lignes de code dans un fichier, avec peu ou pas de commentaires, et le code étant très peu évident
  • Déclarations trop compliquées if. Exemple de code: if (!($lessee_obj instanceof Lessee && $lessee_obj != NULL))que j'ai chopé àif ($lessee_obj == null)
Tarka
la source
7

Code odeur: ne pas suivre les meilleures pratiques

Ce genre de chose m'inquiète toujours car il y a ce truisme que tout le monde pense être un conducteur supérieur à la moyenne.

Voici une nouvelle pour vous: 50% de la population mondiale a une intelligence inférieure à la moyenne. Ok, alors certaines personnes auraient une intelligence tout à fait moyenne, mais ne soyons pas pointilleux. En outre, l'un des effets secondaires de la stupidité est que vous ne pouvez pas reconnaître votre propre stupidité! Les choses ne semblent pas si bonnes si vous combinez ces déclarations.

Quelles sont les choses qui déclenchent instantanément l'alarme lorsque vous regardez un code?

Beaucoup de bonnes choses ont été mentionnées et, en général, il semble que ne pas suivre les meilleures pratiques est une odeur de code.

Les meilleures pratiques ne sont généralement pas inventées au hasard et sont souvent là pour une raison. Plusieurs fois, cela peut être subjectif, mais d'après mon expérience, ils sont principalement justifiés. Suivre les meilleures pratiques ne devrait pas être un problème, et si vous vous demandez pourquoi elles sont ce qu’elles sont, faites des recherches plutôt que de les ignorer et / ou de vous en plaindre - peut-être que cela est justifié, peut-être que non.

Un exemple de meilleure pratique pourrait être d'utiliser des curlies avec chaque if-block, même s'il ne contient qu'une seule ligne:

if (something) {
    // whatever
}

Vous n’allez peut-être pas penser que c’est nécessaire, mais j’ai lu récemment que c’est une source majeure de bugs. Toujours utiliser des crochets a également été discuté sur Stack Overflow , et vérifier que les instructions if ont des crochets est également une règle dans PMD , un analyseur de code statique pour Java.

Rappelez-vous: "Parce que c'est la meilleure pratique" n'est jamais une réponse acceptable à la question "pourquoi faites-vous cela?" Si vous ne pouvez pas expliquer pourquoi quelque chose est une meilleure pratique, alors ce n'est pas une meilleure pratique, c'est une superstition.

Vetle
la source
2
C'est peut-être pédant, mais je pense que la moyenne que vous choisissez est importante. Si je comprends bien, 50% de la population mondiale est en dessous de l'intelligence médiane (par définition); mais d'autres moyennes ne fonctionnent pas de la même manière. Par exemple, prenons la population (1, 1, 1, 5) qui a une moyenne arithmétique de 2.
flamingpenguin
euh, vous avez cité le post "Que-superstitions-do-programmeurs-ont" où un utilisateur a fait une déclaration audacieuse sur les accolades sans source. Je ne vois pas cela comme un bon exemple de meilleures pratiques.
Evan Plaice
@ Evan: oui, vous avez raison. J'ai ajouté un peu plus à ce sujet, espérons que cela aide.
Vetle
4
Le revers de la médaille, ce sont des personnes qui suivent servilement les "meilleures pratiques" sans aucune réflexion critique sur la raison pour laquelle quelque chose est une "meilleure pratique". C'est pourquoi je n'aime pas vraiment l'expression «meilleure pratique», car pour certaines personnes, c'est un prétexte pour arrêter de penser et suivre le troupeau. "Parce que c'est la meilleure pratique" n'est jamais une réponse acceptable à la question "pourquoi faites-vous cela?" Si vous ne pouvez pas expliquer pourquoi quelque chose est une meilleure pratique, alors ce n'est pas une meilleure pratique, c'est une superstition.
Dan Dyer
Très bon commentaire, Dan! J'ai ajouté les deux dernières lignes à la réponse.
Vetle
6

Les commentaires qui disent "c'est parce que la conception du sous-système froz est totalement bouleversée".

Cela va sur un paragraphe entier.

Ils expliquent que le refactor suivant doit se produire.

Mais ne l'a pas fait.

Maintenant, on leur aurait peut-être dit que leur patron ne pouvait pas le changer à l'époque, à cause de problèmes de temps ou de compétences, mais peut-être à cause de la petitesse des gens.

Si un superviseur pense que j.random. le programmeur ne peut pas refactoriser, alors le superviseur devrait le faire.

Quoi qu'il en soit, je sais que le code a été écrit par une équipe divisée, avec une politique de pouvoir possible, et ils n'ont pas refactorisé les conceptions de sous-système bouchées.

Histoire vraie. Ça pourrait t'arriver.

Tim Williscroft
la source
6

Quelqu'un peut-il penser à un exemple où le code devrait légitimement faire référence à un fichier par chemin absolu?

Rei Miyasaka
la source
1
Les schémas XML comptent?
Nick T
1
Fichiers de configuration du système. Cela devrait normalement être défini par ./configure, mais même cela nécessite une valeur par défaut quelque part.
eswald
4
/dev/nullet les amis vont bien. Mais même des choses comme celles-ci /bin/bashsont suspectes - et si vous êtes un système bizarre /usr/bin/bash?
Tom Anderson
1
Le code client du service Web généré par les outils JAX-WS (JBossWS et Metro, au moins) contient un chemin absolu câblé vers le fichier WSDL (deux fois!). Ce qui est probablement quelque chose de très inapproprié comme /home/tom/dev/randomhacking/thing.wsdl. Il est insensé sur le plan criminel qu'il s'agisse d'un comportement par défaut.
Tom Anderson
4
about /dev/null: J'ai l'habitude, lors du développement sur Windows, de conserver les applications et les bibliothèques sous c:\dev. D'une manière ou d'une autre, un dossier nullest toujours automatiquement créé dans ce dossier. Je jure que je n'ai aucune idée de qui fait ça. (Un de mes bugs préférés / fonctionnalités)
Sean Patrick Floyd
6

Saisir les exceptions générales:

try {

 ...

} catch {
}

ou

try {

 ...

} catch (Exception ex) {
}

Surutilisation de la région

Généralement, utiliser trop de régions signifie que vos classes sont trop grandes. C'est un drapeau d'avertissement qui indique que je devrais approfondir cette partie du code.

Erik van Brakel
la source
Capturer les exceptions générales n’est un problème que si vous les renvoyez sans rien faire. Vraiment pour la plupart des choses, une classe d'exception suffirait. J'ai tendance à utiliser runtime_error.
CashCow
+1 pour l'exemple "exception à la capture et au rebut". Si vous ne faites rien avec l'exception, ne l'attrapez pas. À tout le moins, connectez-le. À tout le moins, mettez un commentaire expliquant pourquoi il est normal d'attraper toutes les exceptions et de passer à autre chose dans le code.
EZ Hart
5

Les conventions de dénomination de classe qui démontrent une faible compréhension de l'abstraction qu'elles tentent de créer. Ou qui ne définissent pas du tout une abstraction.

Un exemple extrême me vient à l’esprit dans une classe VB que j’ai vue une fois et qui portait un titre Dataet qui comptait plus de 30 000 lignes… dans le premier fichier. C'était une classe partielle divisée en au moins une demi-douzaine d'autres fichiers. La plupart des méthodes étaient des wrappers entourant des procs avec des noms comme FindXByYWithZ().

Même avec des exemples moins dramatiques, je suis sûr que nous avons tous simplement «jeté» la logique dans une classe mal conçue, en lui attribuant un titre totalement générique, que nous avons regretté par la suite.

Bryan M.
la source
5

Fonctions qui réimplémentent les fonctionnalités de base du langage. Par exemple, si vous voyez une méthode "getStringLength ()" en JavaScript au lieu d'appeler la propriété ".length" d'une chaîne, vous savez que vous avez un problème.

Fourmi
la source
5
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...

Bien sûr, sans aucun type de documentation et les #defines emboîtés occasionnels

Sven
la source
J'ai vu exactement ce "modèle" hier ... dans le code de production ... et même pire ... dans le code de production C ++: - /
Oliver Weiler