Quelles «bonnes pratiques» populaires ne sont pas toujours les meilleures et pourquoi? [fermé]

100

Les "meilleures pratiques" sont omniprésentes dans notre secteur. Une recherche Google sur les "meilleures pratiques de codage" donne près de 1,5 million de résultats. L'idée semble apporter du réconfort à beaucoup; Il suffit de suivre les instructions et tout ira bien.

Lorsque je lis une bonne pratique - par exemple, je viens de lire plusieurs articles récemment dans Clean Code - je suis nerveuse. Est-ce que cela signifie que je devrais toujours utiliser cette pratique? Y at-il des conditions attachées? Y a-t-il des situations où cela pourrait ne pas être une bonne pratique? Comment puis-je savoir avec certitude jusqu'à ce que j'en ai appris davantage sur le problème?

Plusieurs des pratiques mentionnées dans Clean Code ne me convenaient pas, mais honnêtement, je ne sais pas si c'est parce qu'elles sont potentiellement mauvaises, ou si ce sont juste mes préjugés personnels. Je sais que de nombreuses personnalités du secteur des technologies semblent penser qu’il n’ya pas de meilleures pratiques , alors au moins mes doutes persistants me placent en bonne compagnie.

Le nombre de bonnes pratiques que j'ai lues est tout simplement trop important pour être énuméré ici ou poser des questions individuelles, aussi j'aimerais reformuler cette question en une question générale:

Quelles pratiques de codage communément qualifiées de "meilleures pratiques" peuvent être sous-optimales, voire nuisibles dans certaines circonstances? Quelles sont ces circonstances et pourquoi rendent-elles la pratique pauvre?

Je préférerais entendre parler d’exemples et d’expériences spécifiques.

Aaronaught
la source
8
Quelles sont les pratiques avec lesquelles vous n'êtes pas d'accord? Juste curieux.
Sergio Acosta
N'importe qui peut écrire un livre, et je ne suis pas obligé de l'accepter, c'est aussi simple que cela.
Job
Une chose que j’aime dans le livre "Code Complete" de Steve McConnell est qu’il confirme tous ses conseils avec des preuves tangibles et des recherches. Just sayin '
JW01
5
@Walter: C’est ouvert depuis des mois, c’est définitivement constructif, pourquoi le fermer?
Orbling
2
Vu que mon nom est mentionné ici, je suppose que je devrais ajouter: je crois que les réponses ici sont utiles, mais la question pourrait être reformulée en quelque chose de nettement moins semblable à un sondage sans invalider aucune des réponses. Exemple de titre: "Quelles" bonnes pratiques "populaires peuvent parfois être nocives, et quand / pourquoi?"
Aaronaught

Réponses:

125

Je pense que vous avez frappé le clou avec cette déclaration

Je détesterais prendre les choses pour argent comptant et ne pas y penser de façon critique

J'ignore presque toutes les meilleures pratiques sans explications sur les raisons de leur existence

Raymond Chen le dit le mieux dans cet article quand il dit

Un bon conseil vient avec une justification afin que vous puissiez dire quand cela devient un mauvais conseil. Si vous ne comprenez pas pourquoi quelque chose devrait être fait, alors vous êtes tombé dans le piège de la programmation culte du fret, et vous continuerez à le faire même quand ce n'est plus nécessaire ou même devient nuisible.

Conrad Frix
la source
4
Citation merveilleuse.
David Thornley
Le paragraphe suivant de cette citation de Raymond Chen décrit probablement la notation hongroise! La plupart des entreprises que je vois l’utiliser sans aucune raison valable qu’elles puissent expliquer.
Craig
3
J'espère que les gens ne prendront pas cela comme une excuse pour ne pas rechercher le raisonnement derrière les meilleures pratiques. ;) Malheureusement, j'ai vu des développeurs avec cette attitude.
Vetle
3
La raison est bonne. La recherche est meilleure.
Jon Purdy
7
Absolument vrai, et j'ai déjà dit la même chose. Peut-être que la première norme de tout document "Normes" devrait être la suivante: "Dans l’intérêt de partager les connaissances et de fournir les informations nécessaires pour annuler ultérieurement les normes, toutes les normes doivent inclure les raisons de leur existence."
Scott Whitlock
95

On pourrait aussi bien jeter ceci dans le ring:

Premature optimization is the root of all evil.

Non ce n'est pas.

La citation complète:

"Nous devrions oublier les petites économies, disons environ 97% du temps: l'optimisation prématurée est la racine de tous les maux. Cependant, nous ne devrions pas laisser passer nos opportunités dans ces 3% critiques."

Cela signifie que vous tirez parti d' améliorations de performances stratégiques spécifiques tout au long de votre processus de conception. Cela signifie que vous utilisez des structures de données et des algorithmes compatibles avec les objectifs de performance. Cela signifie que vous êtes conscient des considérations de conception qui affectent les performances. Mais cela signifie également que vous n'optimisez pas de manière frivole, car vous obtiendrez des gains mineurs au détriment de la maintenabilité.

Les applications doivent être bien architecturées, pour ne pas tomber à la fin lorsque vous leur appliquez une petite charge, puis vous les réécrivez. Le danger de la citation abrégée est que, trop souvent, les développeurs l'utilisent comme excuse pour ne pas penser à la performance du tout jusqu'à la fin, alors qu'il est peut-être trop tard pour faire quoi que ce soit. Mieux vaut construire dès le départ de bonnes performances, à condition de ne pas se focaliser sur les détails.

Supposons que vous construisez une application en temps réel sur un système intégré. Vous choisissez Python comme langage de programmation, car "l'optimisation précoce est la racine de tout mal". Maintenant , je n'ai rien contre Python, mais il est un langage interprété. Si la puissance de traitement est limitée et qu'un certain volume de travail doit être effectué en temps réel ou quasi réel, et que vous choisissez une langue qui nécessite plus de puissance de traitement que le travail que vous avez, vous êtes royalement bousillé. Il faut maintenant recommencer avec un langage capable.

Robert Harvey
la source
4
+1 pour les forts Non, ce n'est pas.
Stephen
21
Mais si vous avez déjà reconnu qu’une optimisation particulière se situe dans les 3% critiques, êtes-vous prématuré de l’optimiser?
Jean
7
@Robert: Alors quel est le point de désaccord avec l'affirmation selon laquelle "l'optimisation prématurée est la racine de tout mal"?
Jean
8
Il n’est jamais prématuré d’optimiser une conception de haut niveau et des décisions techniques telles que le choix de la langue. Cependant, ce n’est souvent qu’après avoir terminé la conception que ses inefficacités sont mises en évidence. C’est pourquoi Fred Brooks a expliqué que la plupart des équipes écrivent une version à jeter, qu’elles le veuillent ou non. Un autre argument pour le prototypage.
Dominique McDonnell
8
@Robert, la citation de Knuth a été optimisée prématurément ...
94

Un retour par fonction / méthode.

iMacUwhAK
la source
7
J'allais mettre ceci. Je m'aime quelques déclarations de retour au début.
Carson Myers
4
Absolument! Les gens préparent des programmes assez intéressants pour éviter une première returndéclaration. Soit des structures de contrôle profondément imbriquées, soit des contrôles continus. Cela peut vraiment gêner une méthode alors qu’on if returnpourrait vraiment simplifier ce problème.
snmcdonald
4
Si vous avez besoin de plusieurs retours dans une fonction (en dehors des gardes), votre fonction est probablement trop longue.
EricSchaefer
18
Il ne sert à rien d'avoir un mot clé de retour sauf s'il était destiné à apparaître à plusieurs endroits. Revenez tôt, revenez souvent. Cela ne servira qu'à simplifier davantage votre code. Si les gens peuvent comprendre comment fonctionnent les déclarations break / continue, pourquoi ont-ils du mal à obtenir le retour?
Evan Plaice
7
Je pense que c'est une pratique exemplaire très dépassée. Je ne pense pas que ce soit une pratique exemplaire moderne.
Skilldrick
87

Ne pas réinventer la roue est un dogme largement mal utilisé. Son idée est que si une solution appropriée existe, utilisez-la au lieu de créer la vôtre; outre les efforts d’économie, la solution existante est probablement mieux mise en œuvre (sans bug, efficace, testée) que ce que vous auriez proposé au départ. Jusqu'ici tout va bien.

Le problème est qu’il existe rarement une solution adaptée à 100%. Une solution appropriée à 80% pourrait exister, et son utilisation est probablement satisfaisante. Mais qu'en est-il de 60%? 40%? Où tracez-vous la ligne? Si vous ne tracez pas la ligne, vous risquez d'incorporer une bibliothèque saturée à votre projet, car vous utilisez 10% de ses fonctionnalités, simplement parce que vous souhaitez éviter de "réinventer la roue".

Si vous réinventez la roue, vous obtiendrez exactement ce que vous voulez. Vous apprendrez également à fabriquer des roues. Apprendre en faisant ne devrait pas être sous-estimé. Et à la fin, une roue personnalisée pourrait bien être meilleure qu'une roue générique standard.

Joonas Pulakka
la source
3
C'est ce qui s'est passé dans l'autre sens. J'ai construit mon propre composant de grille ajax car, à l'époque, aucun ne faisait ce que je voulais, mais je l'ai ensuite remplacé par des grilles Ext JS. Cela m'a aidé de faire l'hypothèse dès le départ que la couche d'affichage serait remplacée.
Joeri Sebrechts
20
D'accord. Si personne ne réinventait la roue, nous conduirions tous notre voiture avec des pneus en bois.
Apprenti du Dr. Wily le
6
Je me sens toujours comme votre exemple de 10% lorsque j'ajoute Boost à un projet C ++. J'ai toujours besoin de moins de 10% de celui-ci, directement, mais bien sûr, les fonctions dont j'ai besoin importent d'autres modules qui importent d'autres modules ...
Roman Starkov
3
+1: cette semaine seulement, j'ai réinventé la roue (par exemple, remplacer le plugin jquery, à la fois populaire et volumineux, que nous utilisions par quelque chose qui répond à nos besoins, mais modulaire) et cela a entraîné des gains de performances énormes. De plus, il y a des gens dont le travail consiste littéralement à réinventer la roue: prenons, par exemple, Michelin, ils font de la R & D pour améliorer les pneus.
Wildpeaks
2
@Dr. Wily, ces roues n'ont pas été réinventées, elles ont été refactorisées!
78

"Tout tester."

J'ai souvent entendu dire que tous les codes devraient comporter des tests unitaires, ce sur quoi je suis en désaccord. Lorsque vous testez une méthode, toute modification apportée à la sortie ou à la structure de cette méthode doit être effectuée deux fois (une fois dans le code, une fois dans le test).

En tant que tel, les tests unitaires devraient, à mon avis, être proportionnels à la stabilité structurelle du code. Si j'écris un système en couches de bas en haut, ma couche d'accès aux données aura des tests sur le wazoo; ma couche de logique métier sera assez bien testée, ma couche de présentation comportera des tests et mes vues seront peu ou pas testées.

Fishtoaster
la source
7
Je soupçonne que «Tout tester» est devenu un cliché, à l'instar de la citation «d'optimisation prématurée». Je suis généralement d'accord avec vos proportions et j'ai vu de nombreux exemples de développeurs s'efforçant de simuler un objet de couche d'application, effort qui pourrait être mieux dépensé en tests d'acceptation.
Robert Harvey
36
Si un changement dans la structure d'une méthode entraîne une modification de vos tests, vous risquez de ne pas le faire correctement. Les tests unitaires ne doivent pas vérifier la mise en œuvre, mais uniquement le résultat.
Adam Lear
7
@ Anna Lear: Je pense qu'il parlait de faire des changements de conception / structure (refactoring). Étant donné que la conception n’est pas assez mature, lorsque vous trouverez le meilleur moyen de le faire, vous devrez peut-être modifier de nombreux tests. Je conviens que lorsque vous êtes un testeur plus expérimenté, vous remarquerez peut-être plus facilement que l’essai est une mauvaise idée (pour cette raison, entre autres), mais si la conception n’est pas vraiment mature, il est probable que certains façon.
n1ckp
13
Je pense que c’est aussi la raison pour laquelle l’idée de «faire le premier test» ne fonctionne pas. Pour faire les tests en premier, vous devez avoir le bon design. Mais pour que la conception soit correcte, vous devez essayer des solutions et voir comment elles fonctionnent afin de pouvoir les améliorer. Donc, vous ne pouvez pas vraiment faire les tests avant d'avoir la conception, et pour obtenir la bonne conception, vous devez coder et voir comment il fonctionne. À moins que vous n'ayez un très grand architecte, je ne vois pas vraiment comment cette idée fonctionnera.
n1ckp
13
@ n1ck TDD n'est pas réellement un exercice de test, mais bien un exercice de conception. L'idée est de faire évoluer votre conception au moyen de tests (car cela expose rapidement une API raisonnable pour votre matériel) plutôt que de les adapter à une conception existante (qui peut être mauvaise / insuffisante). Donc non, vous n'avez pas besoin de la conception pour faire les tests en premier.
Adam Lear
57

Toujours programmer pour les interfaces.

Parfois, il n'y aura qu'une seule implémentation. Si nous retardons le processus d'extraction d'une interface jusqu'au moment où nous en voyons le besoin, nous constaterons souvent que ce n'est pas nécessaire.

Eric Wilson
la source
4
D'accord, vous programmez une interface lorsque vous avez besoin d'une interface (c'est-à-dire une API stable à partir de laquelle travailler).
Robert Harvey
45
Dans ma lecture, cette règle ne concerne pas les interfaces en tant que constructions de langage. Cela signifie que vous ne devez faire aucune hypothèse sur le fonctionnement interne d'une classe lorsque vous appelez ses méthodes et que vous devez vous fier uniquement aux contrats d'API.
Zsolt Török
2
Ok, voici une question intéressante - je suis principalement un développeur .NET, donc mes interfaces ressemblent à IBusinessManager ou IServiceContract. Pour moi, il est extrêmement facile de naviguer (et je garde généralement mes interfaces dans un autre espace de noms [ou même un autre projet]). Lorsque j’ai utilisé Java, j’ai trouvé cela confus (généralement, les implémentations d’interface que j’ai vu portent un suffixe .impl - et les interfaces n’ont pas de délimitation). Alors, est-ce que cela pourrait être un problème de normes de code? Bien sûr, les interfaces en Java rendent le code encombré - elles ont exactement le même aspect que les classes normales à première vue.
Watson
5
@ Watson: un coût est que chaque fois que j'appuie sur F3 ('saute à la déclaration') lors d'un appel de méthode dans Eclipse, je saute à l'interface, pas à l'implémentation. Je dois ensuite contrôler-T, flèche vers le bas, revenir à la mise en œuvre. Il bloque également certaines refactorisations automatiques. Par exemple, vous ne pouvez pas intégrer une méthode à une définition d'interface.
Tom Anderson
4
@Tom: Eh bien, monsieur, je me ferais un plaisir de vous engager dans cette guerre, Eclipse contre Intellij - mais j'ai un code moral exceptionnel qui m'empêche d'entrer dans des affrontements physiques avec quelqu'un qui a un handicap évident. BOOM. Je ne dis pas que Eclipse est mauvais, je dis que si les puissances de l’Axe l’avaient utilisée pour construire ou concevoir leurs machines de guerre, la Seconde Guerre mondiale serait désormais connue sous le nom de "kerfuffle de deux jours". Sérieusement, j’ai constaté qu’il me manquait un peu de vernis dans les IDE standards (Intellij / VS + ReSharper). Je me suis retrouvé à le combattre à plus d'une occasion - ce qui est une de trop.
Watson
46

N'utilisez rien de code source ouvert (ou non-Microsoft pour vos développeurs .NET)

Si Microsoft ne l'a pas développé, nous ne l'utilisons pas ici. Vous souhaitez utiliser ORM - EF, vous souhaitez utiliser IOC - Unity, vous souhaitez vous connecter - le bloc d'application de journalisation d'entreprise. Il existe de nombreuses bibliothèques de meilleure qualité - et pourtant, je suis toujours coincé dans le menu des dollars du monde du développement. Je jure chaque fois que j'entends les meilleures pratiques de Microsoft que je pense aux "directives nutritionnelles de McDonald's". Bien sûr, vous vivrez probablement si vous les suivez, mais vous serez également mal nourri et en surpoids.

  • Notez que ceci n’est peut-être pas votre meilleure pratique, mais c’est une pratique courante suivie presque partout où j’ai travaillé.
Watson
la source
13
Cela semble horrible ... = (Je suis probablement trop de l'autre côté, cependant, j'évite M $ autant que possible.
Lizzan
Cela ne devrait pas être comme ça. Une bibliothèque doit être choisie pour sa valeur, et pas seulement pour son auteur. Par exemple, j'adore EF mais j'ai eu une mauvaise expérience avec Enterprise Library et j'ai trouvé de meilleurs outils de validation et de journalisation, tels que FluentValidation, log4net et Elmah.
Matteo Mosca
4
Vous ne serez pas viré pour avoir acheté IBM ^ wMicrosoft
Christopher Mahan Le
17
Il existe également la version en miroir, c'est-à-dire, n'utilisez jamais rien de Microsoft, ou n'utilisez jamais quoi que ce soit pour lequel vous devez payer.
Richard Gadsden
5
J'ai la chance de travailler dans une organisation où ce n'est pas un dogme répandu, mais dans les endroits où nous avons adopté des solutions commerciales, la douleur est vive. Le problème survient lorsqu'une partie de la solution commerciale ne fonctionne pas tout à fait. Quand c'est open source, vous pouvez regarder le source (la documentation ultime) et découvrir ce qui ne va pas. Avec le code source fermé, vous devez payer le privilège d’avoir accès aux connaissances du support technique qui en sait encore moins sur le produit que vous utilisez. Et c'est la seule solution disponible.
SingleNegationElimination le
40

Orientation d'objet

Il y a l'hypothèse, juste parce que le code est "orienté objet", c'est magiquement bon. Les gens insèrent donc des fonctionnalités dans des classes et des méthodes, juste pour être orientés objet.

LennyProgrammers
la source
7
Je ne peux pas imaginer construire un logiciel de taille importante sans tirer parti de l'organisation fournie par Object Orientation.
Robert Harvey
18
Robert. Unix n'est pas orienté objet, et il s'agit certainement d'un logiciel de taille importante. Il semble également être assez populaire (pensez Mac OSX, iPhone, téléphones Android, etc.)
Christopher Mahan
7
Ce que je voulais dire, c'est que je pense que nous devrions utiliser la méthodologie la plus appropriée. J'ai vu des gens utiliser des méthodes et des classes trop lourdes et qui n'ont pas beaucoup de sens, simplement parce que "c'est orienté objet". C'est le culte de la cargaison.
LennyProgrammers
8
Il n'y a pas de solution miracle. La programmation fonctionnelle (Haskell) est assez réussie sans être orientée objet. En fin de compte, vous disposez de plusieurs outils et il vous incombe de choisir le meilleur assortiment pour la tâche à accomplir.
Matthieu M.
9
Ce qui est amusant, c’est qu’outre l’utilisation des classes, du polymorphisme et autres, la plupart du code orienté objet est en fait un code procédural.
Oliver Weiler
35

Tout le code doit être commenté.

Non, ça ne devrait pas l'être. Certaines fois, vous avez du code évident, par exemple les setters ne doivent pas être commentés, jusqu'à ce qu'ils fassent quelque chose de spécial. Aussi, pourquoi devrais-je commenter ceci:

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
Vladimir Ivanov
la source
13
Tout le code devrait être compréhensible . Les commentaires sont un outil majeur, mais loin d’être le seul.
Trevel
Absolument, le code devrait être compréhensible. Mais il n'y a pas de raison unique d'écrire un commentaire qui n'ajoute rien, par exemple, au nom de la méthode. Si vous écrivez, /** sets rank. */ void setRank(int rank) { this.rank = rank; }je suppose que le commentaire est stupide. Pourquoi c'est écrit?
Vladimir Ivanov
2
Documentation générée. C'est ce que le /** */format est pour au lieu du /* */commentaire de format. Ou bien pour .NET ce serait///
Berin Loritsch le
10
En utilisant }//end if, }//end for, }//end whilesont le meilleur exemple de gaspillage des commentaires que j'ai jamais rencontré. J'ai souvent vu cela lorsque l'accolade d'ouverture ne dépasse pas deux lignes. IMHO si vous avez besoin de ces commentaires, votre code doit être reconfiguré ... ou vous devez acheter 20 $ et acheter un éditeur de texte / IDE mettant en surbrillance les accolades correspondantes.
Scunliffe
7
Code dit "comment". Les commentaires doivent dire "pourquoi".
32

Méthodologies, particulièrement scrum. Je ne peux pas garder un visage impassible quand j'entends les adultes utiliser la phrase "Scrum Master". J'en ai tellement marre d'entendre les développeurs protester contre certains aspects de Methodology X qui ne fonctionnent pas pour leur entreprise. Seul un gourou m'a dit que cela ne fonctionnait pas parce qu'ils ne sont pas, en fait, de véritables praticiens. de la Méthodologie X. "Scrum Hard, vous devez, mon apprenant Padawan!"

Il existe de nombreuses pépites de sagesse dans les méthodologies agiles - beaucoup d'entre elles - mais elles sont souvent formées dans tellement de fumier que je ne peux pas combattre mon réflexe nauséeux. Prenez ce bit de la page Scrum de Wikipedia :

Un certain nombre de rôles sont définis dans Scrum. Tous les rôles appartiennent à deux groupes distincts - porcs et poulets - en fonction de la nature de leur implication dans le processus de développement.

Vraiment? Porcs et poulets, vous dites? Fascinant! J'ai hâte de présenter celui-ci à mon patron ...

échapper
la source
Intéressant. Je suis d'accord jusqu'à un certain point. Avec cette dernière partie cependant: appelez-les comme vous voulez, ce sont des mnémoniques, c'est tout.
Steven Evers
12
+1 ... vous avez raison, il est difficile de prendre cela au sérieux. <grosse voix en plein essor> * I AM THE SCRUMMASTER * </ voice>
GrandmasterB
2
Et les paraboles. Cela me rappelle des sermons d’église ou des anecdotes qui font la renommée des gourous de l’entraide (et des comédiens): "Prenez mon ami Steve. Steve discutait constamment avec sa femme Sheryl. le point où leur mariage était vraiment en péril. Puis, un jour ... "Ces sortes de fils didactiques ne me dérangent pas dans d'autres domaines, mais je déteste les voir proliférer dans les sciences de l'ingénieur.
evadeflow
2
Qu'en est-il des Ninjas Scrum?
Berin Loritsch
1
Je ne suis pas d'accord avec la comparaison "Pig and Chicken" ... elle va directement à l'encontre du manifeste Agile. À savoir "Collaboration client sur négociation de contrat". Les clients sont aussi investis (sinon plus) dans la réussite du projet que l’équipe de projet. Appeler certains rôles porcs et d'autres rôles poules incarne une mentalité du "nous contre eux" selon laquelle l'IMHO est le plus gros obstacle à la réussite des projets.
Michael Brown
25

Cartographie relationnelle d'objet ... http://en.wikipedia.org/wiki/Object-relational_mapping

Je ne veux jamais être isolé de mes données, ni perdre ce contrôle et cette optimisation précis. Mon expérience avec ces systèmes a été extrêmement médiocre ... Les requêtes générées par ces couches d'abstraction sont encore pires que celles que j'ai pu voir en délocalisation.

Fosco
la source
19
L'optimisation prématurée est la racine de tout Mal. Le code lent n'est, dans la vie réelle, que rarement incroyablement un problème par rapport au code non maintenable. Utilisez un ORM, puis coupez l’abstraction uniquement là où vous en avez besoin.
Fishtoaster
28
Les ORM sont un outil 80-20. Ils sont conçus pour gérer les 80% de CRUD qui deviennent si fastidieux pour écrire tout ce code de plomberie sans fin après un certain temps. Les 20% restants peuvent être réalisés de manière plus "conventionnelle", comme utiliser des procédures stockées et écrire des requêtes SQL ordinaires.
Robert Harvey
18
@Fishtoaster: Ne voulez-vous pas dire: "Nous devrions oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout le mal. Cependant, nous ne devrions pas laisser passer nos opportunités dans ces 3% critiques."?
Robert Harvey
5
@ Robert Harcey: Il y a une raison pour laquelle je n'ai pas utilisé de citation directe. Je pense que la plupart des programmeurs se concentrent trop sur l'efficacité. C'est un problème que peu d'entre eux ont vraiment besoin de résoudre. Certes, il y a des domaines où c'est plus important que d'autres, mais la maintenabilité et l'extensibilité sont un problème partout. Une autre citation modifiée: «Faites-le fonctionner, rendez-le facile à maintenir, rendez-le lisible, rendez-le extensible, rendez-le testable, puis si vous en avez le temps et qu'il s'avère que vous en avez besoin, faites-le rapidement."
Fishtoaster
12
@Craig: Comment n'avez-vous pas reconnu l'ironie dans votre déclaration? Avoir besoin d'un an pour apprendre à obtenir de bonnes performances d'un ORM est un excellent argument contre les ORM, tout comme le besoin de "contrôler" le code SQL produit et d'injecter des procédures stockées. Si vous avez les connaissances pour cela, vous avez les connaissances nécessaires pour contourner entièrement l'ORM.
Nicholas Knight
22

Écrire les noms de fonctions comme s'il s'agissait de phrases anglaises:

Draw_Foo()
Write_Foo()
Create_Foo()

etc. Cela peut sembler génial, mais c'est une douleur lorsque vous apprenez une API. À quel point est-il plus facile de rechercher un index pour "Tout ce qui commence par Foo"?

Foo_Draw()
Foo_Write()
Foo_Create()

etc.

Colen
la source
2
Probablement aussi simple que de taper Foo dans la liste des fonctions de TM.
Josh K
68
On dirait que vous voulez vraiment que ce soit Foo.Draw(), Foo.Write()et Foo.Create()pour que vous puissiez faire Foo.methods.sortouFoo.methods.grep([what I seek]).sort
Inaimathi
7
Commençant par «Get» est un autre exemple.
JeffO
1
Je viens du monde objective-c, et je manque beaucoup de noms de méthodes verbeuses et de notation infixe quand je fais java (mon autre vie). Depuis que le code a commencé à fonctionner, je n’ai pas non plus trouvé le problème de la frappe supplémentaire.
2
@ Scott Whitlock: Pas si obsolète pour certains développeurs .NET, iirc, VS 2008 ne l'a pas fait. 2010 fait cependant, et c'est fantastique.
Steven Evers
22

MVC - Je trouve souvent que résoudre de nombreux problèmes de conception Web dans l'approche MVC consiste davantage à rendre un framework (rails, etc.) plus agréable que la simplicité ou la structure. MVC est un favori des "astronautes de l'architecture" qui semblent privilégier les échafaudages excessifs par rapport à la simplicité. ymmv.

OO basé sur la classe - à mon avis encourage les structures complexes de l'état mutable. les seuls cas convaincants que j'ai trouvés pour OO basé sur les classes au fil des ans sont les exemples "forme-> rectangle-> carré" ringards qui forment le chapitre 1 de n'importe quel livre OO

Brad Clawsie
la source
4
J'ai réalisé du développement Web sous ASP.NET et ASP.NET MVC et, même si MVC semble vraiment échafaudage, je le préfère de loin sur ASP.NET, et ce pour plusieurs raisons: simplicité, maintenabilité et contrôle extrêmement fin du balisage. Tout a sa place et, même si cela semble un peu répétitif, c'est un plaisir de le maintenir. Il est complètement personnalisable, donc si vous n'aimez pas un comportement prêt à l'emploi, vous pouvez le changer.
Robert Harvey
1
En ce qui concerne OO, il existe de bonnes et de mauvaises manières de le faire. L'héritage est surestimé et utilisé avec plus d'économie dans le monde réel que ne le voudraient la plupart des livres. il existe actuellement une tendance vers un style de développement plus fonctionnel et immuable, même dans le monde OO.
Robert Harvey
1
+1 pour mentionner MVC. Bien que le concept de MVC (séparant la logique de couche de données, la logique de présentation et la logique d'arrière-plan soit une bonne idée), séparer physiquement ces éléments dans une hiérarchie de dossiers complexe avec un méli-mélo de fichiers contenant des extraits de code est stupide. Je blâme tout ce phénomène sur le manque de support d'espace de noms en PHP et sur les développeurs débutants qui glorifient des techniques vieilles de plusieurs décennies comme "la chose la plus récente". C'est simple, créez un espace de noms pour les accesseurs de base de données, l'interface graphique et la logique d'arrière-plan (et les sous-espaces de noms si nécessaire).
Evan Plaice
3
En ce qui concerne OO, vous ne verrez pas vraiment ses avantages tant que votre projet n’aura pas atteint une taille telle que la gestion de la complexité devienne importante. Suivez le principe de responsabilité unique chaque fois que cela est possible et, si votre code est accessible publiquement (par exemple, pour un fichier .dll), masquez autant que possible l'implémentation interne de classes / méthodes / propriétés pour sécuriser davantage le code et simplifier l'API.
Evan Plaice
1
Personnellement, je trouve que l'exemple de forme-> rectangle-> carré est l'un des arguments les plus élégants contre oop. par exemple, Square(10).Draw()il suffit de Rectangle(10, 10).Draw(). donc je suppose que cela signifie que carré est une sous-classe de rectangle. Mais mySquare.setWidthHeight(5,10)c’est un non-sens (c’est-à-dire qu’il ne respecte pas le principe de substitution de Liskov), un carré ne peut pas avoir une hauteur et une largeur différentes, contrairement à un rectangle, ce qui implique que ce rectangle est une sous-classe de carrés. Ceci est connu dans d'autres contextes comme "le problème du cercle, de l'ellipse"
SingleNegationElimination le
22

YAGNI

( Vous n'en aurez pas besoin )

Cette approche m'a coûté des heures et des heures lorsque j'ai dû implémenter des fonctionnalités sur une base de code existante, où une planification minutieuse aurait préalablement inclus ces fonctionnalités.

Certaines de mes idées ont souvent été rejetées à cause de YAGNI, et la plupart du temps, quelqu'un devait payer pour cette décision plus tard.

(Bien sûr, on pourrait affirmer qu'une base de code bien conçue permettrait également d'ajouter des fonctionnalités ultérieurement, mais la réalité est différente)

Sean Patrick Floyd
la source
15
Je suis d'accord avec YAGNI, mais je vois où vous voulez en venir. Le but de YAGNI est de s’adresser aux personnes qui souhaitent tout planifier dans les moindres détails. Neuf fois sur dix cependant, cela sert d'excuse pour sous-concevoir le code d'ingénieur ou pour ignorer complètement la planification.
Jason Baker
12
P.Floyd, @Jason Baker: +1 Absolument juste. Le vieil adage s'applique ici: "Des mois dans le laboratoire peuvent faire économiser des heures à la bibliothèque"
Steven Evers,
Une spécification laissera souvent (et devrait principalement) laisser la plupart de l'implémentation et une partie de l'interface ouverte. tout ce qui n'est pas directement dans la spécification, mais requis pour l'implémenter, qu'il s'agisse d'une décision de mise en œuvre, d'une interface visible par l'utilisateur ou de toute autre chose, est également une exigence indirecte de la spécification. Si une fonctionnalité n'est pas dans la spécification, et n'est pas impliquée par la spécification, vous n'en avez pas besoin. Comment cela peut-il être déroutant?
SingleNegationElimination
1
@TokenMacGuy l'aspect crucial est l' impliqué par la partie spec . C'est là que les opinions diffèrent beaucoup.
Sean Patrick Floyd le
20

Pour SQL

  1. Ne pas utiliser de déclencheurs
  2. Toujours masquer les tableaux derrière les vues

En ordre:

  1. Ils sont une caractéristique qui a sa place. Vous avez plusieurs chemins de mise à jour vers une table ou avez besoin d'un audit à 100%?

  2. Juste pourquoi? Je le ferais si je refactaisais pour maintenir un contrat, mais pas après avoir lu que les gens modifiaient la vue pour correspondre aux changements de table

Modifier:

Numéro 3: Éviter * avec EXISTS. Essayez 1/0. Ça marche. La liste de colonnes n'est pas évaluée selon le standard SQL. Page 191

milliard
la source
3
# 2 est une meilleure pratique?
Hogan
1
@Hogan: une vue qui reflète simplement une table de base n'ajoute aucune sécurité par rapport à l'utilisation directe de la table de base. Si vous vous associez à une table securityuser, ou masquez certaines colonnes, faites-le correctement. Mais CHOISISSEZ chaque colonne de la table ou de la vue: aucune différence. Personnellement, j'utilise quand même des procs stockés.
gbn
3
@Hogan: Je sais quelque chose à propos de SQL Server :-) stackoverflow.com/users/27535/gbn Ce que je veux dire, c'est que GRANT SELECT sur la table n'est pas différent de GRANT SELECT ON VIEW si la vue est SELECT * FROM TABLE
gbn
1
@gbn: je suis d'accord. Il n'y a pas de différence là-bas. Je pense que nous pourrions dire la même chose. J'imagine que mon commentaire initial ("Le n ° 2 est une pratique exemplaire?") Reposait davantage sur mon expérience personnelle selon laquelle les vues (comme les déclencheurs) sont plus souvent mal utilisées que correctement utilisées. Ainsi, une telle pratique exemplaire ne conduirait qu'à des abus et non à une amélioration. Si cela est considéré comme une pratique exemplaire, vous avez entièrement raison, c’est une mauvaise pratique.
Hogan
20

Modèles de conception principalement. Ils sont trop utilisés et sous-utilisés.

Geek
la source
13
+1 Je ne vois toujours pas en quoi les modèles de conception sont des solutions élégantes ou élégantes. Ce sont des solutions de rechange aux problèmes de langage, rien de plus.
Oliver Weiler
2
Voyez-le simplement comme une tentative d'éliminer l'odeur de la langue en utilisant la langue elle-même.
Filip Dupanović
15

Le principe de responsabilité unique

("chaque classe ne devrait avoir qu'une seule responsabilité; en d'autres termes, chaque classe devrait avoir une et une seule raison de changer")

Je ne suis pas d'accord. Je pense qu'une méthode ne doit avoir qu'une raison de changer et que toutes les méthodes d'une classe doivent avoir une relation logique entre elles , mais la classe elle-même peut en réalité faire plusieurs choses (liées).

D'après mon expérience, ce principe est trop souvent appliqué avec trop de zèle et vous aboutissez à de nombreuses petites classes à une méthode. Les deux magasins agiles où j'ai travaillé l'ont fait.

Imaginez si les créateurs de l'API .Net avaient eu ce genre de mentalité: plutôt que List.Sort (), List.Reverse (), List.Find (), etc., nous aurions des classes ListSorter, ListReverser et ListSearcher!

Plutôt que de me disputer davantage contre le PÉR (qui en soi n’est pas terrible en théorie) , je vais partager quelques-unes de mes longues expériences anecdotiques:


À un endroit où j’ai travaillé, j’ai écrit un solveur de flux max très simple composé de cinq classes: un nœud, un graphe, un créateur de graphes, un solveur de graphes et une classe permettant d’utiliser les créateurs / solveurs de graphes pour résoudre un problème. problème du monde réel. Aucun n'était particulièrement complexe ou long (le solveur était de loin le plus long à environ 150 lignes). Cependant, il a été décidé que les classes avaient trop de «responsabilités», alors mes collègues se sont mis à la refactorisation du code. Quand ils ont fini, mes 5 classes ont été étendues à 25 classes, dont le nombre total de lignes de code était plus du triple de ce qu’elles étaient à l’origine. Le flux du code n'était plus évident, pas plus que l'objectif des nouveaux tests unitaires; J'avais maintenant du mal à comprendre ce que mon propre code faisait.


Au même endroit, presque toutes les classes n’avaient qu’une seule méthode (sa seule "responsabilité"). Suivre le déroulement du programme était presque impossible, et la plupart des tests unitaires consistaient à vérifier que cette classe appelait du code provenant d' une autre classe , dont le but était également un mystère pour moi. Il y avait littéralement des centaines de classes où il aurait fallu (IMO) seulement des dizaines. Chaque classe ne faisait qu'une "chose" , mais même avec des conventions de nommage telles que "AdminUserCreationAttemptorFactory" , il était difficile de dire la relation entre les classes.


À un autre endroit (qui avait également la mentalité classes-devrait-avoir-seulement-une-méthode ), nous essayions d'optimiser une méthode qui prenait 95% du temps au cours d'une certaine opération. Après (plutôt bêtement) l’optimiser un peu, j’ai tourné mon attention vers pourquoi on l’appelait des bajillions de fois. Il était appelé dans une boucle d'une classe ... dont la méthode était appelée dans une boucle d'une autre classe .. qui était également appelée dans une boucle ..

En tout, il y avait cinq niveaux de boucles répartis sur 13 classes (sérieusement). Il était impossible de déterminer ce qu’une classe faisait réellement en la regardant: vous deviez dessiner un graphe mental de ses méthodes, des méthodes appelées par ces méthodes, et ainsi de suite. Si tout avait été regroupé dans une seule méthode, il n'aurait fallu que 70 lignes de long avec notre méthode par problème imbriquée dans cinq niveaux de boucles immédiatement évidents.

Ma demande de refactoriser ces 13 classes en une seule classe a été refusée.

BlueRaja - Danny Pflughoeft
la source
6
On dirait que quelqu'un a "Pattern Fever" ou dans ce cas "Principle Fever" à cet emploi. La classe list ne viole pas SRP. Toutes ses fonctions servent un seul but, manipulant une collection d'objets. Avoir une seule fonction dans une classe me semble excessif. Le principe de base de SRP est qu'une unité de code (que ce soit une méthode, une classe ou une bibliothèque) devrait avoir une responsabilité unique qui peut être énoncée succinctement.
Michael Brown
3
J'ai commencé à voir ce genre de folie de la part de personnes qui trouvent impossible d'écrire du code fonctionnel pur et simple. Trop éduquer pour que tous les problèmes du monde puissent être résolus à partir d'un livre de modèles. Pas assez de réflexion sur le pragmatisme. Comme vous, j'ai vu un code OO basé sur les classes tellement horrible qu'il est absolument impossible de le suivre. Et son énorme et gonflé.
Rapidement maintenant
3
2ème commentaire ici. Beaucoup de "principes" sont sur-appliqués. Il y a beaucoup de bonnes idées pour lesquelles faire le contraire est parfois approprié. Les bons programmeurs savent quand ils enfreignent les règles. Parce que les règles ne sont pas des "règles", ce sont des déclarations de "bonne pratique la plupart du temps sauf lorsque c'est une idée vraiment stupide".
Rapidement maintenant
"Imaginez si les créateurs de l'API .Net avaient eu ce genre de mentalité: plutôt que List.Sort (), List.Reverse (), List.Find () etc., nous aurions des classes ListSorter, ListReverser et ListSearcher. ! ". C’est exactement ce qui se fait en C ++, et c’est merveilleux . Les algorithmes sont séparés des structures de données. Par conséquent, si j'écris mon propre conteneur, tous les algorithmes fonctionnant avec la bibliothèque standard fonctionnent uniquement avec mon nouveau conteneur. Cela doit être horrible en .Net land, en écrivant une nouvelle fonction de tri pour chaque nouveau conteneur que vous voulez trier.
Mankarse
14

Maintenant que vous avez mentionné Clean Code, bien qu'il contienne de bonnes idées, je pense que son obsession de refactoriser toutes les méthodes en sous-méthodes et celles en sous-méthodes, etc. est beaucoup trop poussée. Au lieu de quelques méthodes à dix lignes, vous êtes censé préférer vingt-un (soi-disant bien nommés). Évidemment, quelqu'un pense que c'est propre, mais pour moi, cela semble bien pire que la version originale.

En outre, le remplacement de simples choses élémentaires telles que

0 == memberArray.length

dans une classe avec un appel à la méthode de la classe, telle que

isEmpty()

est une "amélioration" discutable IMHO. Addition: la différence est que la première vérification fait exactement ce qu'elle dit: vérifie si la longueur du tableau est égale à 0. Ok, isEmpty()peut aussi vérifier la longueur du tableau. Mais cela pourrait aussi être implémenté comme ceci:

return null != memberArray ? 0 == memberArray.length : true;

C'est-à-dire qu'il inclut un contrôle nul implicite! Cela peut être un bon comportement pour une méthode publique - si le tableau est null, alors quelque chose est certainement vide - mais lorsque nous parlons d'internals de classe, cela ne va pas si bien. Bien que l’encapsulation à l’extérieur soit indispensable, les internes de la classe doivent savoir exactement ce qui se passe dans la classe. Vous ne pouvez pas encapsuler la classe à partir de elle-même . Explicite est meilleur qu'implicite.


Cela ne veut pas dire que la décomposition de méthodes longues ou de comparaisons logiques impliquées ne soit pas une bonne chose; bien sûr, mais dans quelle mesure le faire - là où se situe le bonbon - est évidemment une question de goût. Décomposer une méthode longue entraîne davantage de méthodes, et ce n'est pas gratuit. Vous devez parcourir le code source pour voir ce qui se passe réellement, quand vous pourrez le voir en un coup d'œil si tout cela était dans une seule méthode.

J'irais même jusqu'à dire que dans certains cas, une méthode d'une ligne est trop courte pour mériter d'être une méthode.

Joonas Pulakka
la source
6
Je vois rarement cela comme un problème. C'est surtout parce que je vois souvent trop d'une seule méthode, pas trop peu. Cependant, selon certaines études, la très faible complexité des méthodes présente également un taux de bogues légèrement supérieur à celui de la complexité modérément basse. enerjy.com/blog/?p=198
MIA
Oui, c’est vraiment un problème dans Clean Code uniquement. Dans la vie réelle, les méthodes ont tendance à être trop longues, comme vous l'avez dit. Mais c'est intéressant de voir cette courbe! En effet, les choses devraient être aussi simples que possible, mais pas plus simples.
Joonas Pulakka
1
Je trouve votre deuxième exemple éminemment plus lisible, et cette forme (ou quelque chose de similaire, comme une propriété Length sur la classe elle-même) est un must si vous le rendez public.
Robert Harvey
@ Robert Harvey: Le deuxième exemple est une bonne méthode publique, mais l'appeler depuis la classe elle-même est discutable, car vous ne savez pas exactement ce que ça fait avant de regarder comment elle est implémentée. Il pourrait vérifier null, par exemple. Voir mon ajout ci-dessus.
Joonas Pulakka
@Joonas: Assez bien.
Robert Harvey
13

"Soyez libéral avec des commentaires"

Les commentaires sont définitivement une bonne chose, mais un trop grand nombre d’entre eux est tout aussi mauvais sinon pire que pas assez. Pourquoi? Eh bien, les gens ont tendance à écarter les commentaires s’ils en voient trop. Je ne dis pas que vous pouvez avoir un code parfaitement auto-documenté, mais il est préférable de coder pour avoir besoin de commentaires pour des explications.

Jason Baker
la source
1
Le code auto-documenté est vraiment agréable. Bien que j'aime avoir des commentaires à côté de quelque chose comme des calculs simples (pour exprimer ce que le type de retour ou la valeur retournée est). Toutefois, si vos commentaires nécessitent plus de mots que le code lui-même, il est probablement temps de le réécrire.
Sova
6
Je suis d'accord avec la façon dont sova a mis celui-ci. Un code propre est préférable aux commentaires.
Riwalk
4
Vous avez toujours besoin du "pourquoi" ici!
Je préférerais avoir des commentaires expliquant pourquoi. Cela signifie que je dois PENSER moins en ingénierie inverse de l'intention du code lorsque je viens de l'examiner.
Rapidement maintenant
12

GoTo considéré comme nuisible

Si vous implémentez une machine à états, une instruction GOTO peut avoir plus de sens (lisibilité et code efficace) qu'une approche de "programmation structurée". Cela a vraiment inquiété certains collègues lorsque la première partie de code que j'ai écrite dans un nouvel emploi comprenait non pas une mais plusieurs déclarations de goto. Heureusement, ils étaient suffisamment intelligents pour comprendre que c’était la meilleure solution dans ce cas particulier.

Toute "meilleure pratique" qui ne permet pas d'exceptions raisonnables et documentées à ses règles est tout simplement effrayante.

MZB
la source
16
Je passe neuf ans à programmer sans une seule déclaration goto (y compris plusieurs machines à états, comme vous l'avez mentionné). Développez votre esprit à de nouvelles idées.
Riwalk
3
@Mathieu M. - D'accord - Mélanger GOTO avec des instructions de contrôle structurées n'est pas judicieux. (C était pur et ce n’était pas un problème.
MZB
1
@ Stargazer2 - avec un FSM simple, cela dépend si placer l'état dans une variable et l'utiliser comme index pour appeler une procédure (n'est-ce pas la même chose qu'un GOTO calculé?) Donne un code plus clair / plus rapide que d'utiliser le compteur de programme comme l'état FSM. Je ne préconise pas que ce soit la meilleure solution dans la plupart des cas, mais simplement la meilleure dans certaines circonstances. Développez votre esprit aux approches alternatives.
MZB
5
@MZB, ne conviendriez-vous pas qu'un appel de fonction est aussi simplement un GOTO calculé? Il en va de même pour les constructions for / while / if / else / switch, entre autres. Les concepteurs de langage font abstraction des modifications directes apportées au compteur de programme pour une raison. Ne pas utiliser goto.
Riwalk
3
La mise en œuvre directe d'une machine à statuer est probablement un anti-modèle. Il y a beaucoup de façons d'avoir une machine à états sans exprimer littéralement les états et les transitions. par exemple,import re
SingleNegationElimination
12

Les sacrifices que nous faisons pour rendre le code testable

Je saute à travers de nombreuses étapes pour rendre mon code testable, mais je ne prétends pas que je ne le ferais pas si j'avais le choix. Cependant, j'entends souvent des gens insister pour que ce soient des "meilleures pratiques". Ces pratiques incluent (écrites dans la langue de .Net, mais s’appliquent aussi à d’autres langues) :

  • Créer une interface pour chaque classe. Cela double le nombre de classes (fichiers) à traiter et duplique le code. Oui, la programmation d'interface est bonne, mais c'est à quoi servent les spécificateurs public / privé.
  • Chaque classe non instanciée au démarrage nécessite une fabrique. Clairement, new MyClass()c'est beaucoup plus simple que d'écrire une fabrique, mais maintenant la méthode qui la crée ne peut pas être testée séparément. Sinon, je ne ferais que 1 / 20e du nombre de classes d’usine que je fais maintenant.
  • Rendre chaque classe publique, ce qui va à l’encontre de l’obtention de spécificateurs d’accès sur les classes. Cependant, les classes non publiques ne sont pas accessibles (et donc testées) à partir d'autres projets. La seule autre option consiste à déplacer tout le code de test dans le même projet (et donc à le publier avec le produit final).
  • Injection de dépendance. Clairement, le fait de donner à chaque autre classe un champ et un paramètre constructeur représente beaucoup plus de travail que de simplement les créer lorsque j'en ai besoin; mais alors je ne peux plus tester cette classe en isolation.
  • Le principe de responsabilité unique, qui m'a causé tant de maux de tête que je l'ai déplacé vers sa propre réponse .

Alors, que pourrions-nous faire pour résoudre ce problème? Nous aurions besoin d'un changement radical dans l'architecture de la langue:

  • Nous aurions besoin de la capacité de se moquer des cours
  • Nous aurions besoin de la possibilité de tester des méthodes privées de classes internes provenant d'un autre projet (cela peut sembler être une faille de sécurité, mais je ne vois pas de problème si le client est obligé de nommer ses classes de test) .
  • L'injection de dépendance (ou le site de service), ainsi que quelque chose d'équivalent à notre modèle d'usine existant, devrait être une partie essentielle de la langue.

En bref, nous avons besoin d’ un langage conçu à partir de la base avec à l’esprit la testabilité .

BlueRaja - Danny Pflughoeft
la source
Je suppose que vous n'avez jamais entendu parler de TypeMock ? Il permet des cours moqueurs, des cours privés, de la statique (usine), n'importe quoi.
Allon Guralnek
@Allon: Oui, mais c'est loin d'être gratuit , ce n'est donc pas une option pour la plupart des gens.
BlueRaja - Danny Pflughoeft le
Si vous devez écrire beaucoup de cours d'usine, vous faites quelque chose de mal. Les bibliothèques Smart DI (par exemple, Autofac pour C #) peuvent utiliser Func <T>, Lazy <T>, Délégués, etc., pour les usines, sans écrire vous-même de passe-partout.
Gix
10

Séparer les applications en niveaux; Couche de données, couche métier, couche d'interface utilisateur

La principale raison pour laquelle je n'aime pas cela est que la plupart des endroits qui suivent cette méthode utilisent des cadres très fragiles pour le faire. La couche d'interface utilisateur IE est codée à la main pour traiter les objets de la couche de gestion, tandis que la base de données est SQL et est déjà assez fragile et est gérée par le groupe "DBA" qui n'aime pas les modifications.

Pourquoi est-ce mauvais? La demande d'amélioration la plus courante est probablement "J'ai besoin d'un champ sur l'écran X qui a Y". Coup! Vous avez juste une nouvelle fonctionnalité qui affecte chaque couche, et si vous séparez des couches avec différents programmeurs, cela devient simplement un gros problème impliquant plusieurs personnes et groupes, pour un changement très simple.

De plus, je ne sais pas combien de fois je me suis disputé avec des arguments similaires. "Le champ du nom est limité à 30 caractères. S'agit-il d'un problème de couche d'interface utilisateur, de couche métier ou de couche de données?" Et il y a cent arguments, et aucune bonne réponse. La réponse est la même, elle affecte toutes les couches, vous ne voulez pas rendre l'interface utilisateur stupide et devez parcourir toutes les couches et échouer au niveau de la base de données, juste pour que l'utilisateur découvre que son entrée est trop longue. Si vous le modifiez, cela affecte toutes les couches, etc.

Les "couches" ont tendance à fuir également; Si une couche est physiquement séparée par des limites de processus / de machines (interface utilisateur Web IE et logique d'arrière-plan métier), les règles sont dupliquées pour que tout fonctionne raisonnablement bien. Par exemple, une logique métier aboutit dans l'interface utilisateur, même s'il s'agit d'une "règle de gestion", car l'utilisateur a besoin que l'interface utilisateur soit réactive.

Si le cadre utilisé, ou l'architecture utilisée, est résistant aux petites modifications et aux fuites, c'est-à-dire qu'il repose sur des métadonnées et qu'il est ajusté de manière dynamique dans toutes les couches, cela peut être moins pénible. Mais la plupart des frameworks représentent une douleur royale, nécessitant des modifications de l'interface utilisateur, de la couche de gestion et de la base de données, pour chaque modification mineure, et générant plus de travail et moins d'aide que celle que la technique est censée produire.

Je vais probablement être critiqué pour cela, mais voilà :)

Geai
la source
+1, cela ressemble à mon dernier lieu d’emploi dans les moindres détails! Je respecte les applications à plusieurs niveaux par principe, mais trop de gens le traitent comme une solution miracle quand cela n’a aucun sens. La plupart des logiciels de gestion ont une logique de gestion extrêmement faible et ses fonctionnalités sont relativement simples. Cela peut faire de la logique métier de superposition un cauchemar du code passe-partout. Bien souvent, les lignes peuvent devenir floues entre l'accès aux données et la logique métier car la requête est la logique métier.
maple_shaft
En outre, la plupart des magasins ne reconnaissent absolument pas la logique de l'interface utilisateur ou de la présentation. Comme ils ne comprennent pas le peu de logique métier dans une application CRUD typique, ils se sentent obligés de commettre une erreur lorsque la majeure partie de leur logique réside dans la couche de présentation en tant que logique de présentation. Elle est faussement identifiée en tant que logique métier, puis les personnes le transmettent au serveur pour un autre appel de serveur. Un client léger peut et doit avoir une logique de présentation, par exemple. (Cachez textField2 si l'option1 est sélectionnée dans dropDown3).
maple_shaft
7

Histoires d'utilisateurs / Cas d'utilisation / Personas

 

Je comprends la nécessité de ces éléments lorsque vous programmez une industrie que vous ne connaissez pas bien, mais je pense que lorsqu'ils sont mis en œuvre de manière pleinement effective, ils deviennent trop corporatifs et deviennent une perte de temps.

riwalk
la source
7

Les limites de 80 caractères / ligne sont muettes

Je comprends que certains compromis doivent être faits pour correspondre au rythme du coureur le plus lent du côté de l'interface graphique (limitations de résolution d'écran, etc.), mais pourquoi cette règle s'applique-t-elle au formatage du code?

Voir ... Il y avait cette petite invention appelée la barre de défilement horizontale qui a été créée pour gérer l'espace d'écran virtuel en dehors de la limite de pixels la plus à droite. Pourquoi les développeurs, qui ont réussi à créer d'excellents outils d'amélioration de la productivité, tels que la coloration syntaxique et l'auto-complétion, ne l'utilisent pas?

Bien sûr, il existe des éditeurs CLI religieusement utilisés par les dinosaures * nix qui respectent les anciennes limitations fatiguées de leurs terminaux VT220, mais pourquoi sommes-nous tenus de respecter les mêmes normes?

Je dis, vis la limite de 80 caractères. Si les dinosaures sont assez épiques pour pirater emacs / vim toute la journée, pourquoi ne devraient-ils pas être capables de créer une extension encapsulant automatiquement des lignes ou offrant des capacités de défilement horizontal à leurs IDE CLI?

Les moniteurs 1920x1080 pixels deviendront éventuellement la norme et les développeurs du monde entier continueront de vivre dans les mêmes limites, sans se soucier de savoir pourquoi, sauf que c'est ce que leurs aînés leur avaient demandé de faire lorsqu'ils commençaient tout juste à programmer.

Les limites de 80 caractères ne sont pas une pratique exemplaire mais une pratique de niche pour une très petite minorité de programmeurs et doivent être traitées comme telles.

Modifier:

Il est compréhensible que de nombreux développeurs n'aiment pas la barre de défilement horizontale car elle nécessite un geste de la souris alors ... Pourquoi ne pas augmenter la limite de largeur de colonne à un nombre plus élevé (que 80) pour ceux d'entre nous qui utilisent des écrans modernes.

Lorsque les écrans 800x600 sont devenus la norme pour la plupart des utilisateurs, les développeurs Web ont augmenté la largeur de leur site Web pour répondre aux besoins de la majorité ... Pourquoi les développeurs ne peuvent-ils pas en faire autant?

Evan Plaice
la source
1
@Orbling Nice, la logique GWB avec le ___ est un mauvais angle. Donc, vous détestez le hScroll, avez-vous une raison valable pour laquelle la largeur de col devrait être limitée à 80 caractères? Pourquoi pas 160 ou 256? Je pense que nous pouvons tous supposer que la plupart des développeurs ont abandonné leurs terminaux VT220 et les ont remplacés par des puTTY, ce qui leur permet d’agrandir la largeur par programmation de toute façon.
Evan Plaice
4
Je préfère que nous nous en tenions à la limite de 80 caractères. Dès que vous me donnez plus d'espace horizontal, je vais essayer d'ouvrir des documents supplémentaires côte à côte avec le reste. Je détesterais devoir faire défiler quatre manières. De plus, j'ai souvent remarqué que je suis obligé d'écrire du code plus lisible avec le capuchon de 80 caractères.
Filip Dupanović
2
comment voudriez-vous l'imprimer?
5
Désolé, je ne suis pas d'accord avec celui-ci. Je déteste vraiment les longues lignes - il faut plus de mouvement des yeux, il faut que les gestes de la souris défilent, il est plus difficile de voir subtilement de petites choses sans fin au bout d'une ligne. Dans environ 99% des cas, il existe des moyens propres de faire passer un contenu sur plusieurs lignes (plus courtes), ce qui est plus clair et plus facile à lire. 80 Les caractères peuvent être arbitraires et "parce que c'était comme ça les jours avec des cartes perforées" mais c'est toujours un cadre raisonnable pour travailler à l'intérieur - la plupart du temps - pour les raisons ci-dessus.
Rapidement maintenant
3
Indentation de 2 espaces. Et utilisez un éditeur avec un traqueur d'indentation automatique. Je le fais depuis des années, ce n'est pas grave. (Emacs avec les bons modes aide ici.)
rapidement le
5

Mesurer, mesurer, mesurer

Tellement bien, mesurez-le, mais pour isoler les bugs de performance, la mesure fonctionne à la fois comme une élimination successive. Voici la méthode que j'utilise.

J'ai essayé de localiser la source de la mesure-mesure "sagesse". Quelqu'un avec une caisse à savon assez grande l'a dit, et maintenant ça voyage.

Mike Dunlavey
la source
5

Mon professeur exige que je commence tous mes identifiants (sans les constantes) avec des lettres minuscules, par exemple myVariable.

Je sais que cela semble être une chose mineure, mais de nombreux langages de programmation exigent des variables pour commencer par des lettres majuscules. J'apprécie la cohérence, c'est donc mon habitude de tout commencer par des lettres majuscules.

Maxpm
la source
9
J'ai eu un enseignant qui avait besoin de camelCase parce qu'il insistait sur le fait que c'était ce que les gens utilisent dans le monde réel ... En même temps, je programmais dans deux groupes différents de mon travail - les deux groupes insistaient sur les scores inférieurs. Ce qui compte, c'est ce que votre groupe utilise. Il aurait pu se définir en tant que programmeur principal et tout se passerait bien dans mon livre - nous suivons ses conventions - mais il donnait toujours son opinion comme "la façon dont les choses se passent dans le monde réel" comme s'il n'y avait pas d'autre solution valable. façon.
Xnine
@xnine Je n'ai pas encore assez de représentants sur ce site pour évaluer votre commentaire, je vais donc vous répondre avec ce commentaire d'approbation.
Maxpm
5
L'affaire Camel (première lettre minuscule) est une convention assez courante, ainsi que l'affaire Pascal (première lettre de chaque mot en majuscule). Dans la plupart des langues, camelCase est utilisé sur des variables privées / internes, et PascalCase sur des classes, méthodes, propriétés, espaces de noms, variables publiques. Ce n’est pas une mauvaise pratique que de s’habituer à être prêt pour des projets pouvant utiliser un schéma de nommage différent.
Evan Plaice
2
Juste un FYI. Certaines langues déduisent la signification de savoir si la première lettre d'une variable est capitale ou non. Dans l'une de ces langues, si la première lettre est une majuscule, la variable est traitée comme une constante. Toute tentative de la modifier renverra une erreur.
Berin Loritsch
1
Dans Go , les méthodes publiques et les membres des classes commencent par une lettre majuscule; les privés avec une lettre minuscule.
Jonathan Leffler
5

Utilisez Singletons

Quand vous ne devriez avoir qu'une seule instance de quelque chose. Je ne peux pas être en désaccord plus. N'utilisez jamais un singleton, allouez-le une seule fois et passez le pointeur / objet / la référence selon les besoins. Il n'y a absolument aucune raison de ne pas le faire.

utilisateur2528
la source
2
C'est tout un tas de points négatifs qui m'ont laissé plutôt confus quant à votre position actuelle sur les singletons.
Paul Butcher
1
@ Paul Butcher: Je déteste les singletons et il ne devrait jamais être utilisé
1
@ rwong: Personnellement, je ne pense pas qu'une raison soit une raison légitime. Il suffit d'écrire comme une classe normale. En réalité, il n'y a aucune raison d'utiliser un singleton autre que la paresse et de promouvoir de mauvaises habitudes ou un mauvais design.
6
Qui a dit que l'utilisation de Singeltons était la meilleure pratique?
Phil Mander
2
Les singletons ont leur place, en particulier dans les cas où une structure opérationnelle est allouée et remplie au démarrage, puis deviennent fondamentalement en lecture seule pendant toute la durée d'exécution du programme. Dans ce cas, il devient simplement un cache de l’autre côté du pointeur.
Tim Post
5

Utiliser unsigned int comme itérateur

Quand apprendront-ils que l'utilisation de Int signé est beaucoup plus sûre et moins sujette aux bogues? Pourquoi est-il si important que l'index d'un tableau ne puisse être qu'un nombre positif, que tout le monde est heureux de passer à côté du fait que 4 - 5 correspond à 4294967295?

AareP
la source
Ok, maintenant je suis curieux, pourquoi dites-vous cela? Je me sens un peu stupide - pouvez-vous fournir des exemples de code pour sauvegarder vos déclarations?
Paul Nathan
4
@Paul Nathan: en ce qui concerne le problème, voici un exemple: for (unsigned int i = 0; i <10; i ++) {int crash_here = my_array [max (i-1,0)];}
AareP
@AareP: Pour être sûr - je présume que vous faites référence au fait que lorsqu'un décrochage d'un entier non signé 0est décrémenté 1, vous vous retrouvez avec la valeur positive maximale qu'un stockant non signé peut stocker?
Adam Paynter
1
@Adam Paynter: oui. Cela peut sembler normal pour les programmeurs c ++, mais avouons-le, "unsigned int" est une mauvaise "implémentation" de nombres positifs seulement.
Août
Ce n’est pas une bonne idée sur les petites machines embarquées - des ints souvent non signés généreront un code plus petit et plus rapide. Dépend du compilateur et du processeur.
Rapidement maintenant
4

Les méthodes ne doivent pas être plus longues qu'un seul écran

Je suis tout à fait d'accord avec le principe de responsabilité unique, mais pourquoi les gens le perçoivent-il comme signifiant "une fonction / méthode ne peut avoir qu'une seule responsabilité au niveau le plus détaillé de granularité logique"?

L'idée est simple. Une fonction / méthode doit accomplir une tâche. Si une partie de cette fonction / méthode peut être utilisée ailleurs, découpez-la en sa propre fonction / méthode. S'il peut être utilisé ailleurs dans le projet, déplacez-le dans sa propre classe ou dans une classe utilitaire et rendez-le accessible en interne.

Avoir une classe qui contient 27 méthodes d'assistance appelées une seule fois dans le code est stupide, c'est une perte de place, une complexité inutile et une perte de temps considérable. Cela semble plutôt être une bonne règle pour les personnes qui veulent avoir l’air occupé à refactoriser le code mais qui ne produisent pas beaucoup.

Voici ma règle ...

Écrire des fonctions / méthodes pour accomplir quelque chose

Si vous êtes sur le point de copier / coller du code, demandez-vous s'il serait préférable de créer une fonction / méthode pour ce code. Si une fonction / méthode n'est appelée qu'une fois dans une autre fonction / méthode, y a-t-il vraiment un intérêt à l'avoir en premier lieu (l'appellera-t-elle plus souvent à l'avenir)? Est-il utile d’ajouter plus de sauts dans les fonctions / méthodes lors du débogage (c’est-à-dire que le saut ajouté rend le débogage plus facile ou plus difficile)?

Je suis tout à fait d’accord pour dire que les fonctions / méthodes de plus de 200 lignes doivent être vérifiées, mais certaines fonctions n’accomplissent qu’une tâche sur autant de lignes et ne contiennent aucune partie utile pouvant être abstraite / utilisée dans le reste du projet.

Je le regarde du point de vue de l'API dev ... Si un nouvel utilisateur examinait le diagramme de classes de votre code, combien de parties de ce diagramme auraient un sens dans l'ensemble du projet et combien existeraient uniquement des aides à d’autres parties internes au projet.

Si je devais choisir entre deux programmeurs: le premier a tendance à écrire des fonctions / méthodes qui tentent de faire trop; le second casse chaque partie de chaque fonction / méthode au plus fin niveau de granularité; Je choisirais les premières mains. Le premier en ferait plus (c’est-à-dire, rédigerait plus de viande de l’application), son code serait plus facile à déboguer (en raison du nombre réduit de sauts dans les fonctions / méthodes pendant le débogage), et il perdrait moins de temps à travailler, à perfectionner le code semble vs perfectionner la façon dont le code fonctionne.

Limitez les abstractions inutiles et ne polluez pas la saisie semi-automatique.

Evan Plaice
la source
Cette. Une fois, j'ai refactoré une longue fonction en plusieurs, mais je me suis rendu compte que presque toutes avaient besoin de presque tous les paramètres du code d'origine. La manipulation des paramètres était si pénible qu'il était plus facile de revenir à l'ancien code.
l0b0
3
Je pense qu'un contre-argument à cela est que refactoriser des parties d'une grande méthode en appels séparés peut rendre la méthode plus grande plus facile à lire. Même si la méthode n'est appelée qu'une fois.
Jeremy Heiler
1
@ Jeremy Comment? En résumé, comment résumer une section de code et la placer dans sa propre méthode la rend plus lisible que de simplement placer un commentaire d'une ligne en haut de cette portion de code décrivant ce qu'il fait? En supposant que ce bloc de code est utilisé une seule fois dans cette section de code. Est-il vraiment si difficile pour la plupart des programmeurs de décomposer les parties actives du code lorsqu'ils le lisent et / ou de placer quelques commentaires d'une ligne pour leur rappeler ce qu'il fait s'ils ne le peuvent pas?
Evan Plaice
4
@ Evan: Le fait de mettre des morceaux de code dans des fonctions leur donne un nom et leur explique, espérons-le, ce que fait ce morceau de code. Maintenant, quel que soit le code appelé, vous pouvez voir le nom expliquer ce que fait le code , au lieu d'avoir à analyser et à comprendre l'algorithme lui-même. Bien fait, cela peut grandement faciliter la lecture et la compréhension du code.
sbi
1
+1 et je donnerais plus si je pouvais. Il n'y a rien de mal avec un bloc de code C contenant 1000 lignes dans une seule fonction (par exemple, un analyseur avec un switch ()) énorme FOURNI l'intention est claire et simple. Supprimer tous les petits morceaux et les appeler rend la chose plus difficile à comprendre. Bien sûr, il y a aussi des limites à cela… un jugement sensé est tout.
Rapidement maintenant