Quels sont les pires anti-patterns que vous ayez rencontrés dans votre carrière de programmeur?
Je suis principalement impliqué dans java, bien qu'il soit probablement indépendant de la langue.
Je pense que le pire est ce que j'appelle le principal anti-modèle . Cela signifie un programme composé d'une seule classe extrêmement grande (parfois accompagnée d'une paire de petites classes) qui contient toute la logique. Généralement avec une grande boucle dans laquelle toute la logique métier est contenue, ayant parfois des dizaines de milliers de lignes de code.
language-agnostic
anti-patterns
стривігор
la source
la source
J'en frapperai une autre évidente avec des "copier-pâtes". Copier du code presque identique à ce que vous voulez, puis changer quelques éléments (au lieu de l'extraire dans une méthode).
Ceci est particulièrement répandu dans certains codes de test fonctionnel et API de la fin des années 90: littéralement des centaines (voire des milliers) de cas de test presque identiques qui auraient pu être décomposés en quelques fonctions qui prennent 3 ou 4 paramètres - ou, mieux encore , quelque chose basé sur les données. Mon premier travail hors de l'université a été littéralement 8 mois de réécriture et de refactorisation de milliers de lignes de pâtes à copier qui utilisaient des méthodes obsolètes. Au moment où j'ai terminé, les fichiers de test étaient inférieurs à un dixième de leur taille d'origine et beaucoup plus faciles à maintenir (et lisibles!).
la source
Je pense que je peux écrire beaucoup sur Pattern Mania et des solutions qui pourraient être résolues avec beaucoup moins d'efforts, mais je préfère pointer vers un excellent article que j'ai lu récemment avec un exemple fantastique de la façon dont une solution simple peut être trop compliquée. .
Comment (pas) écrire Factorial en Java ou alors nous mettons une usine dans votre algorithme
la source
Marteau d'or
la source
Régions
En C #, vous pouvez définir une région de code qui peut être réduite dans l'IDE, le masquant ainsi à moins que vous ne vouliez traiter ce code. J'ai été (je suis actuellement sur) un projet où les régions s'étalaient sur des centaines de lignes (j'aurais aimé exagérer) et il y avait plusieurs régions dans une fonction à mille lignes (encore une fois, je voudrais plaisanter).
En revanche, le développeur qui a créé la région a très bien identifié les fonctions spécifiques d'une région. À tel point que j'ai pu faire une méthode d'extraction sur la région et passer à autre chose.
Les régions encouragent les développeurs à "cacher" leurs conneries à la vue.
la source
DoNotUseRegions
.#region SQL Update
rend pliable, donc moins de défilement est nécessaire.Pour moi, le pire modèle est le copier / coller .
la source
Pas de méthodes de surcharge:
Montre clairement que le programmeur n'a pas compris la surcharge.
la source
Séquences de commutateur de boucle
http://en.wikipedia.org/wiki/Loop-switch_sequence
Ils m'ennuient sans fin et montrent vraiment à quel point le développeur était inexpérimenté
la source
Le codage logiciel , c'est-à-dire lorsque les programmeurs font tout leur possible pour éviter le codage en dur et se retrouvent de l'autre côté de l'échelle - les dépendances "codées en dur".
la source
Gardez l'état dans le client.
Une fois travaillé avec une application Web où tout état était conservé dans le navigateur. (Pour garantir une évolutivité sans problème, toutes les exceptions ont été ignorées).
la source
Checkins massifs
Je déteste quand je vois qu'un développeur ne s'est pas enregistré depuis plus d'une semaine. Cela signifie qu'il est coincé et n'a pas cherché d'aide, ou qu'il regroupe un tas de fonctionnalités en un seul enregistrement. (J'ai laissé de côté le pire des cas, il ne fait rien du tout. C'est facile à résoudre ... deux mots semblent être embauchés.)
Si vous effectuez un enregistrement important, vous perdez de nombreux avantages de SCM, comme la possibilité de lier un ensemble de modifications à une fonctionnalité spécifique. De plus, vous aurez probablement beaucoup de fusion à faire et ce n'est pas nécessairement facile de bien faire les choses.
la source
Actuellement, je travaille avec un morceau de code hérité et j'aime la façon dont le codeur précédent obtient le premier élément d'une liste:
Mais à mon humble avis, le pire que j'ai vu dans ce code est de définir des classes de pages JSP en ligne, d'écrire tout le HTML, CSS et Javascript en utilisant le scriptlet et out.println :-(
la source
L'un des pires anti-modèles comportementaux que j'ai vus était un magasin qui ne permettait que le code à vérifier dans le contrôle de version après sa production. Couplé avec des extractions exclusives dans VSS, cela a conduit à un processus compliqué d'annulation des extractions si un défaut de production devait être corrigé avant la prochaine version, sans parler de plus d'une personne devant modifier un fichier donné pour la prochaine version.
Le fait qu'il s'agissait d'une politique ministérielle l'a rendu encore pire que le cas d'un seul développeur se comportant de cette façon.
la source
Verrouillage d'un littéral de chaîne
Noms de classe très longs. (dans le JRE)
Mauvaise structure d'héritage
Une exception qui ne l'est pas.
Gestion des erreurs inutiles et cryptiques
Création inutile d'objets
Lancer une exception à d'autres fins
Utilisation d'objets d'instance pour des méthodes statiques.
Synchronisation sur un champ non final
Copie inutile d'une chaîne constante
Appel inutile à String.toString ()
Appels à System.gc () pour libérer de la mémoire
Définition de la variable locale sur null pour libérer de la mémoire
Utiliser ++ i au lieu d'i ++ pour des raisons de performances (ou toute autre micro-micro-optimisation)
la source
Code saupoudré de:
ou
sans aucune information supplémentaire.
la source
Itérateur pour les nuls:
Singletono-Factory:
développement axé sur le cas contraire (également appelé principe de fermeture ouverte - ouvert à la modification proche à la compréhension):
StringPattern (également appelé StringObject):
la source
else if
souvent alors le seul moyen de faire avancer les choses. Je pense aux cordes; ne peut pas utiliser un interrupteur. Les conditions doivent être similaires pour qu'il soit utile.getInstance
renvoie la même instance. Une telle hypothèse briserait l'encapsulation et est en fait l'un des anti-schémas les plus courants.Ce n'est pas tellement un modèle de codage mais un modèle de comportement, c'est assez mauvais cependant: modifier quelque chose dans le code (disons que les exigences ont changé), puis peaufiner tous les tests unitaires jusqu'à ce que le code le réussisse. Ajuster ou simplement supprimer tout le code de test de la méthode de test, mais en laissant la méthode là.
Ceci est lié à un modèle plus générique, le modèle That'll Do , voici une ligne de code représentative:
Cela fonctionne, après tout.
la source
Je méprise absolument l'inversion d'abstraction , ou la réinvention de primitives de bas niveau par-dessus les primitives de haut niveau. Parfois, cependant, cela est dû à de mauvais concepteurs de langage, pas à de mauvais programmeurs. Exemples:
Utiliser une seule classe de méthode sans variable membre et une interface correspondante, (implémentée en termes de tables de pointeurs de fonction), au lieu d'un pointeur de fonction. Notez que dans des langages comme Java, vous n'avez peut-être pas le choix.
Dans MATLAB et R, l'insistance que tout est un vecteur / matrice plutôt qu'une primitive.
Pendant que nous dénigrons MATLAB, qu'en est-il du fait qu'il n'a pas d'entiers, donc quand vous avez besoin d'un entier, vous devez utiliser un double.
Langages purement fonctionnels où vous devez utiliser des appels de fonction pour écrire une boucle.
la source
Ce serait certainement copier / coller, j'ai vu beaucoup de mauvais code se faire à cause de cela, cela et le codage cowboy et tout ce qui en découle. (Classes divines, méthodes extra larges, algorithmes mal pensés, etc.)
Et si les modèles de conception sont autorisés, je dirais: faire un projet comme un ensemble d'actions à partir d'un plan, sans faire de conception ou d'analyse de domaine.
la source
Haricot Java multi-usage -
Un bean java avec beaucoup de variables, utilisé dans différents types d'opérations. Chaque opération utilise un sous-ensemble arbitraire des variables du bean et ignore les autres. Quelques variables pour l'état de l'interface graphique, quelques variables jetées pour le passage entre les composants, quelques-unes qui ne sont probablement plus utilisées. Les meilleurs exemples n'ont pas de documentation, ce qui entraverait l'appréciation du modèle.
Aussi, je ne peux pas oublier le bien-aimé
la source
Un ancien collègue avait l'habitude de réutiliser des objets en écrasant leurs propriétés, au lieu d'en créer simplement de nouvelles. Je n'aurais jamais pu imaginer la quantité de problèmes que cela a causés lors de la mise en œuvre de nouvelles fonctionnalités.
la source
Quelque chose qui m'a causé beaucoup de chagrin est le motif "Grande carte dans le ciel". Lancer autour d'une carte au lieu d'utiliser des objets appropriés. Vous n'avez aucune idée des «variables» qu'il contient sans débogage et vous ne savez pas ce qu'il pourrait contenir sans remonter le code en arrière. Mappe généralement les chaînes aux objets, ou les chaînes aux chaînes, que vous êtes censé potentiellement analyser en primitives.
la source
L'un de mes modèles anti-développement préférés est l'utilisation d'une «conception» de base de données qui nécessite l' ajout continu de colonnes supplémentaires à une ou plusieurs tables par programme . Il s'agit d'un cousin de la "conception" qui crée une nouvelle table pour chaque instance d'une entité. Les deux atteignent inévitablement les limites du serveur de base de données, mais généralement pas avant que le système soit en production depuis un certain temps.
la source
Je pense que l'un des pires anti-modèles que j'ai vus implique l'utilisation d'une table de base de données comme stockage temporaire au lieu d'utiliser la mémoire de l'ordinateur.
Le domaine du problème est propriétaire, ce qui m'interdit de l'expliquer, mais il n'est pas nécessaire de comprendre le problème de base. Il s'agissait d'une application graphique écrite en Java avec une base de données backend. Il s'agissait de prendre certaines données d'entrée, de les manipuler puis de valider les données traitées dans la base de données.
Notre projet a un algorithme assez compliqué qui enregistre des valeurs intermédiaires pour un traitement ultérieur. Au lieu d'encapsuler les objets temporaires dans ... des objets, une table de base de données a été créée comme "t_object". Chaque fois qu'une valeur était calculée, elle était ajoutée à ce tableau. Une fois que l'algorithme a terminé son travail, il sélectionnerait toutes les valeurs intermédiaires et les traiterait toutes dans un grand objet Map. Une fois tout le traitement terminé, les valeurs restantes marquées pour être enregistrées seraient ajoutées au schéma de base de données réel et les entrées temporaires dans la table "t_object" seraient supprimées.
Le tableau était également utilisé comme une liste unique, les données ne pouvaient exister qu'une seule fois. Cela aurait pu être une caractéristique décente de la conception si nous avions implémenté des contraintes sur la table, mais nous avons fini par parcourir toute la table pour voir si les données existaient ou non. (Non, nous n'avons même pas utilisé de requêtes utilisant des clauses where avec CONTAINS)
Certains des problèmes que nous avons rencontrés en raison de cette conception étaient spécifiquement le débogage. L'application a été conçue pour acheminer les données de sorte qu'il y ait plusieurs interfaces graphiques graphiques qui pré-traiteraient les données avant d'arriver à cet algorithme. Le processus de débogage consistait à traiter un cas de test, puis à faire une pause juste après avoir terminé la section ci-dessus. Ensuite, nous interrogions la base de données pour voir quelles données étaient contenues dans ce tableau.
Un autre problème que nous avons découvert était que les données n'étaient pas supprimées correctement de cette table temporaire, ce qui pourrait interférer avec les exécutions à l'avenir. Nous avons découvert que cela était dû au fait que les exceptions n'étaient pas correctement gérées et que, par conséquent, l'application ne se fermait pas correctement et ne supprimait pas les données de la table dont elle avait le contrôle.
Si nous avions utilisé la conception orientée objet de base et conservé tout en mémoire, ces problèmes ci-dessus ne se seraient jamais produits. Tout d'abord, le débogage aurait été simple car nous pourrions facilement configurer des points d'arrêt dans l'application, puis inspecter la mémoire dans la pile et le tas. Deuxièmement, en cas de sortie anormale de l'application, la mémoire java aurait été nettoyée naturellement sans avoir à se soucier de la supprimer de la base de données.
REMARQUE: je ne dis pas que ce modèle est intrinsèquement mauvais, mais dans cet exemple, je l'ai trouvé inutile lorsque les principes de base OO auraient suffi.
Je ne suis pas sûr d'un nom pour cet anti-modèle car c'est la première fois que je vois quelque chose comme ça fait. Y a-t-il de bons noms auxquels vous pouvez penser pour ce modèle?
la source
Chariot avant le cheval - alias YouMightNeedIt
Par exemple:
la source
L'OMI, le pire anti-modèle que j'ai vu, c'est l'anti-modèle "Nous n'avons pas besoin de modèles puants": L'idée que les modèles de conception sont des pertes de temps et que vous pouvez écrire du code plus rapidement en le coupant ensemble et en copiant / coller au besoin.
Une mention honorable va au code qui charge un objet à partir de la base de données en utilisant l'ancien style VB6 de:
pas vraiment un anti-modèle en soi, mais montre un manque de tirer parti de l'architecture appropriée et de la séparation des préoccupations.
De plus, des choses comme ça:
la source