Pourquoi tout le monde me dit-il d’écrire du code comme si c’était une mauvaise pratique?
if (foo) Bar(); //or for(int i = 0 i < count; i++) Bar(i);
Mon plus grand argument pour l’omission des accolades est qu’elles peuvent parfois être deux fois plus nombreuses. Par exemple, voici un code pour peindre un effet lumineux pour une étiquette en C #.
using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor))) { for (int x = 0; x <= GlowAmount; x++) { for (int y = 0; y <= GlowAmount; y++) { g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y)); } } } //versus using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor))) for (int x = 0; x <= GlowAmount; x++) for (int y = 0; y <= GlowAmount; y++) g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));
Vous pouvez également profiter de l’avantage de chaîner les usings
sans avoir à usings
un million de fois.
using (Graphics g = Graphics.FromImage(bmp)) { using (Brush brush = new SolidBrush(backgroundColor)) { using (Pen pen = new Pen(Color.FromArgb(penColor))) { //do lots of work } } } //versus using (Graphics g = Graphics.FromImage(bmp)) using (Brush brush = new SolidBrush(backgroundColor)) using (Pen pen = new Pen(Color.FromArgb(penColor))) { //do lots of work }
L’argument le plus courant pour les accolades tourne autour de la programmation de la maintenance et des problèmes qui en découleraient en insérant du code entre l’original if et son résultat prévu:
if (foo) Bar(); Biz();
En fait, le seul moment où je me suis vraiment senti était quand j’étais en train de déboguer, et commenté bar ():
if(foo) // bar(); doSomethingElse();
A part ça, j’ai tendance à utiliser:
if(foo) bar();
Qui prend en charge le cas ci-dessus.
EDIT Merci d’avoir clarifié la question, je suis d’accord, nous ne devrions pas écrire le code au plus petit dénominateur commun.
Vitesse de lecture …
Mis à part ce qui a déjà été mentionné. À ce stade, j’ai déjà été conditionné à parsingr si les instructions avec des accolades et des espaces blancs. Alors j’ai lu:
if (condition) { DoSomething(); } DoSomethingElse();
Un peu plus vite que je lis:
if (condition) DoSomething(); DoSomethingElse();
Je le lis un peu plus lentement s’il ressemble à ceci:
if (condition) DoSomething(); DoSomethingElse();
J’ai lu ceci beaucoup plus lentement que le précédent:
if (condition) DoSomething(); DoSomethingElse();
beause je ne peux pas m’empêcher de le relire juste dans le cas et se demander si l’auteur a voulu:
if (condition) { DoSomething(); DoSomethingElse(); }
Déjà abordé en général, mais quand il s’agit de lire le texte ci-dessous, je vais me pencher sur ce sujet pendant un certain temps pour vérifier ce que l’auteur a voulu. Je peux même rechercher l’auteur original pour confirmer.
if (condition) DoSomething(); DoSomethingElse();
Si c’est quelque chose de petit, écrivez-le comme ceci:
if(foo()) bar();
Si c’est assez long pour se briser en deux lignes, utilisez des accolades.
J’avais aussi l’habitude de penser qu’il est préférable de n’utiliser que des accolades lorsque cela est vraiment nécessaire. Mais plus maintenant, la raison principale, lorsque vous avez beaucoup de code, le rend plus lisible et vous pouvez parsingr le code plus rapidement lorsque vous avez un style de contreventement cohérent.
Une autre bonne raison de toujours utiliser des accolades, en plus de quelqu’un qui ajoute une seconde déclaration au if, est quelque chose comme ceci:
if(a) if(b) c(); else d();
Avez-vous remarqué que la clause else est en fait celle de “if (b)”? Vous l’avez probablement fait, mais est-ce que vous feriez confiance à quelqu’un pour connaître ce gotcha?
Donc, juste pour la cohérence et parce que vous ne savez jamais quelles choses inattendues peuvent se produire lorsque quelqu’un d’autre (c’est toujours les autres qui sont stupides) modifie le code, je mets toujours des accolades, car cela rend le code source plus lisible ton cerveau. Ce n’est que pour les instructions simples les plus simples, comme si une délégation est créée ou si elle est similaire à un commutateur, lorsque vous savez que la clause ne sera jamais étendue, je laisserais de côté les accolades.
Je préfère la clarté qu’offre le corset. Vous savez exactement ce que l’on veut dire et vous n’avez pas à deviner si quelqu’un a fait une bêtise et l’a laissé (et a introduit un bug). La seule fois où je les omet, c’est quand je mets le if et l’action sur la même ligne. Je ne le fais pas très souvent non plus. Je préfère en fait les espaces introduits en plaçant les accolades sur leur propre ligne, bien que des années de programmation de type K & R, terminer la ligne avec une accolade soit une pratique à laquelle je dois travailler si l’EDI ne l’exige pas. moi.
if (condition) action(); // ok by me if (condition) // normal/standard for me { action(); }
Ce n’est pas toujours considéré comme une mauvaise pratique. Les directives de codification du projet Mono suggèrent de ne pas utiliser d’accolades si cela n’est pas nécessaire. La même chose pour les normes de codage GNU . Je pense que c’est une question de goût personnel, comme toujours avec les normes de codage.
Les lignes sont bon marché. La puissance du processeur est bon marché. Le temps du développeur est très cher.
En règle générale, à moins que je développe une application absolument indispensable pour les ressources / la vitesse, je me tromperais toujours du côté de l’écriture de code qui est
(a) Facile pour tout autre développeur de suivre ce que je fais
(b) Commenter des parties spécifiques du code qui peuvent en avoir besoin
(c) Facile à déboguer si quelque chose ne va pas
d) Facile à modifier s’il doit être à l’avenir (par exemple, append / supprimer du code)
La rapidité ou l’élégance académique du code est secondaire à ces facteurs du sharepoint vue de l’entreprise. Cela ne veut pas dire que je me suis mis à écrire du code maladroit ou laid, mais ceci est mon ordre de priorité.
En omettant les accolades dans la plupart des cas, cela rend (b), (c) et (d) plus difficiles pour moi (notez cependant que ce n’est pas impossible). Je dirais que l’utilisation d’accolades ou non n’a pas d’effet sur (a).
Je pense que c’est une question de lignes direcsortingces pour le projet sur lequel vous travaillez et les goûts personnels.
Je les omet généralement quand ils ne sont pas nécessaires, sauf dans certains cas comme les suivants:
if (something) just one statement; // i find this ugly else { // many // lines // of code }
je préfère
if (something) { just one statement; // looks better:) } else { // many // lines // of code }
L’un des cas où cela peut vous mordre est de retour dans les temps anciens des macros C / C ++. Je sais que c’est une question C #, mais souvent les normes de codage sont conservées sans les raisons pour lesquelles la norme a été créée en premier lieu.
Si vous ne faites pas très attention lorsque vous créez vos macros, vous pouvez vous retrouver avec des problèmes avec les instructions if qui n’utilisent pas le {}.
#define BADLY_MADE_MACRO(x) function1(x); function2(x); if (myCondition) BADLY_MADE_MACRO(myValue)
Maintenant, ne vous méprenez pas, je ne dis pas que vous devriez toujours faire {} juste pour éviter ce problème en C / C ++, mais j’ai dû faire face à des bogues très étranges à cause de cela.
J’ai l’habitude de penser de la même manière.
Jusqu’à ce qu’un jour (pourquoi y a-t-il toujours un “jour” qui change votre vie pour toujours?), Nous passons de 24 à 36 heures sans sumil à déboguer le code de production uniquement pour découvrir que quelqu’un n’a pas .
C’était quelque chose comme ça.
if( debugEnabled ) println( "About to save 1 day of work to some very important place."); saveDayData();
Ce qui est venu après était
if( debugEnabled ) // println( "About to save 1 day of work to some very important place."); saveDayData();
Il s’avère que le système générait 500 Mo de journaux par jour et on nous a demandé de l’arrêter. L’indicateur de débogage n’était pas suffisant et une recherche et remplacer println était en ordre.
Lorsque l’application a été mise en production, l’indicateur de débogage s’est éteint et l’important «saveDayData» n’a jamais été appelé.
MODIFIER
Maintenant, le seul endroit où je n’utilise pas les accolades est la construction if / try.
if( object != null ) try { object.close(); } catch( .....
Après avoir vu un développeur de superstar le faire.
Pour être franc, je le vois comme:
Les bons programmeurs programment défensivement, les mauvais programmeurs ne le font pas.
Puisqu’il y a plusieurs exemples ci-dessus et mes propres expériences similaires avec des bogues liés à l’oubli d’appareils, j’ai appris la voie difficile pour TOUJOURS METTRE DES BRACES.
Tout le rest, c’est choisir un style personnel plutôt que la sécurité et c’est clairement une mauvaise programmation.
Joel mentionne même cela dans Making Wrong Code Look Wrong
Une fois que vous avez été attaqué par un bogue à cause d’accolades manquantes, vous apprenez que les accolades manquantes ne sont pas correctes, car vous savez qu’il est possible qu’un autre bogue se produise.
Je suis très content de:
foreach (Foo f in foos) foreach (Bar b in bars) if (f.Equals(b)) return true; return false;
Personnellement, je ne vois pas pourquoi
foreach (Foo f in foos) { foreach (Bar b in bars) { if (f.Equals(b)) { return true; } } } return false;
est plus lisible.
Oui, les lignes sont gratuites, mais pourquoi devrais-je faire défiler les pages et les pages de code alors que la taille pourrait être inférieure de moitié?
S’il y a une différence de lisibilité ou de maintenabilité, alors, bien sûr, mettez des accolades … mais dans ce cas, je ne vois aucune raison de le faire.
Aussi, je mettrai toujours des accolades pour imbriquer si c’est où j’ai nested les autres
if (condition1) if (condition2) doSomething(); else (condition2) doSomethingElse();
contre
if (condition1) if (condition2) doSomething(); else (condition2) doSomethingElse();
est terriblement déroutant, donc je l’écris toujours comme:
if (condition1) { if (condition2) doSomething(); else (condition2) doSomethingElse(); }
Dans la mesure du possible, j’utilise des opérateurs ternaires, mais je ne les niche jamais .
Je suis d’accord que “si vous êtes assez intelligent pour amener quelqu’un à vous payer pour écrire du code, vous devriez être assez intelligent pour ne pas compter uniquement sur l’indentation pour voir le stream du code.”
Cependant … des erreurs peuvent être commises, et celle-ci est un mal à déboguer … surtout si vous regardez le code de quelqu’un d’autre.
Ma philosophie est que si cela rend le code plus lisible, pourquoi ne pas le faire?
Évidemment, vous devez tracer la ligne quelque part, comme trouver ce juste milieu entre des noms de variables concis et trop descriptifs. Mais les crochets évitent vraiment les erreurs et améliorent la lisibilité du code.
Vous pouvez faire valoir que les personnes assez intelligentes pour être des codeurs seront assez intelligentes pour éviter les bogues qui réduisent les déclarations sans support. Mais pouvez-vous honnêtement dire que vous n’avez jamais été dérangé par quelque chose d’aussi simple qu’une faute d’orthographe? Minutia comme ça peut être écrasant quand on regarde de grands projets.
Il y a toujours des exceptions, mais je ne voudrais pas omettre les accolades seulement quand il est dans l’une des formes:
if(x == y) for(/* loop */) { //200 lines } //rampion's example: for(/* loop */) { for(/* loop */) for(/* loop */) { //several lines } }
Sinon, je n’ai aucun problème avec ça.
J’utilise occasionnellement le code le plus bas (plusieurs instructions), mais à part cela, je mets toujours les accolades. Je trouve que cela rend le code plus clair. Il est évident que plus qu’une simple indentation qu’une déclaration fait partie d’un bloc (et donc probablement une partie d’un if, etc.).
J’ai vu le
if (...) foo(); bar();
bug mord moi (ou plutôt “moi et collègues” – je n’ai pas introduit le bug) une fois . C’était malgré le fait que nos normes de codage à l’époque recommandaient d’utiliser des accolades partout. Il m’a fallu beaucoup de temps pour repérer, car vous voyez ce que vous voulez voir. (C’était il y a environ 10 ans. Peut-être que je trouverais plus vite maintenant.)
Bien sûr, si vous utilisez “accoler à la fin de la ligne”, cela réduit les lignes supplémentaires, mais je n’aime pas ce style. (Je l’utilise au travail et je l’ai trouvé moins désagréable que prévu, mais c’est quand même un peu désagréable.)
Parmi les trois conventions:
if(addCurleyBraces()) bugFreeSofware.hooray();
et:
if(addCurleyBraces()) bugFreeSofware.hooray();
et (qui représentent tout style d’indentation en utilisant une accolade et une accolade):
if(addCurleyBraces()) { bugFreeSofware.hooray(); }
Je préfère le dernier comme:
Je suis impressionné et humilié que mes pairs dans ce domaine de la programmation informatique (vous êtes nombreux) ne soient pas découragés par la perspective de bogues potentiels lorsque vous ignorez les accolades sur des blocs de lignes simples.
Je suppose que cela signifie que je ne suis pas intelligent. J’ai fait des erreurs à plusieurs resockets. J’ai débogué les erreurs des autres autour de cela. J’ai regardé des logiciels livrés avec des bogues à cause de cela (RDP sur une machine fonctionnant avec VS2002 et votre police de la fenêtre de la montre deviendra difficile).
Si je regarde toutes les erreurs que j’ai commises qui auraient pu être évitées avec un changement de style de codage, la liste est très longue. Si je n’avais pas modifié mon approche dans chacun de ces cas, je ne l’aurais probablement jamais fait en tant que programmeur. Encore une fois, je suppose que je ne suis pas intelligent. Pour compenser, je suis un utilisateur de longue date des accolades sur des blocs d’une seule ligne.
Cela dit, certaines choses ont changé dans le monde, ce qui rend la règle «tu utiliseras des accolades sur des blocs d’une seule ligne» moins pertinente aujourd’hui que lorsque Moïse nous l’a fait comprendre:
Certains langages populaires éliminent le problème en faisant lire l’indentation par l’ordinateur, comme le fait le programmeur (par exemple, Python).
Mon éditeur formate automatiquement pour moi, donc les chances que je sois induit en erreur par une indentation sont très réduites.
TDD signifie que si j’introduis un bogue parce que je suis confus par un bloc d’une seule ligne, je suis beaucoup plus susceptible de découvrir le bogue rapidement.
Le refactoring et l’expressivité du langage signifient que mes blocs sont beaucoup plus courts et que les blocs d’une seule ligne sont beaucoup plus fréquents que d’habitude. En théorie, avec une application impitoyable d’ExtractMethod, je ne pourrais avoir que des blocs d’une seule ligne dans tout mon programme. (Je me demande à quoi ça ressemblerait?)
En fait, il y a un avantage certain à refactoriser des accolades impitoyables et omises sur des blocs à une seule ligne: lorsque vous voyez des accolades, une petite alarme peut apparaître dans votre tête, indiquant «la complexité ici! Imaginez si c’était la norme:
if (condition) Foo(); // normal, everyday code if (condition) { // something non-sortingvial hapening; pay attention! Foo(); Bar(); }
Je me lance à l’idée de changer ma convention de codage en quelque chose comme “des blocs d’une seule ligne peuvent ne jamais avoir d’accolades” ou “si vous pouvez placer le bloc sur la même ligne que la condition, omettre les accolades “. Nous verrons.
Vos principaux arguments contre l’utilisation d’accolades sont qu’elles utilisent des lignes supplémentaires et qu’elles nécessitent un retrait supplémentaire.
Les lignes sont (presque) gratuites, minimiser le nombre de lignes dans votre code ne devrait pas être un objective.
Et l’indentation est indépendante de l’utilisation des accolades. Dans votre exemple d’utilisation en cascade, je pense toujours que vous devriez les mettre en retrait même lorsque vous omettez les accolades.
Je suis un fervent partisan de l’écriture de code concis, mais j’utiliserais toujours des accolades. Je trouve qu’ils sont un moyen pratique de voir rapidement le champ d’application d’une ligne de code particulière. Il n’y a pas d’ambiguïté, c’est juste explicitement exposé devant vous.
Certains peuvent dire que c’est un cas de préférence, mais je trouve que le stream logique d’un programme est beaucoup plus facile à suivre s’il est cohérent en interne, et je ne pense pas qu’il soit cohérent d’écrire une telle instruction IF;
if(x < y) x = y; else y = x;
Et un autre comme ça;
if(x < y) { x = y; x++; } else { y = x; y++; }
Je préfère choisir un style général et m'en tenir à ça 🙂
Ok, c’est une vieille question à laquelle on a répondu à mort. J’ai quelque chose à append
Je dois d’abord dire UTILISER LES BRACES. Ils ne peuvent que consortingbuer à la lisibilité, et la lisibilité (pour vous-même et les autres!) Devrait figurer en tête de votre liste de priorités à moins que vous n’écriviez un assemblage. Le code illisible conduit toujours à des bogues. Si vous trouvez que les accolades font que votre code prend trop de place, vos méthodes sont probablement trop longues. La plupart ou la totalité des méthodes doivent correspondre à une hauteur d’écran si vous le faites correctement, et Find (F3) est votre ami.
Maintenant pour mon ajout: Il y a un problème avec ceci:
if (foo) bar();
Essayez de définir un point d’arrêt qui ne sera touché que si bar () est exécuté. Vous pouvez le faire en C # en plaçant le curseur sur la seconde moitié du code, mais ce n’est pas évident et c’est un peu pénible. En C ++, vous ne pouviez pas le faire du tout. L’un de nos développeurs les plus expérimentés travaillant sur le code C ++ insiste pour que les instructions if soient divisées en deux lignes. Et je suis d’accord avec lui.
Alors faites ceci:
if (foo) { bar(); //It is easy to put a breakpoint here, and that is useful. }
L’un des principaux problèmes est lorsque vous avez des régions de lignes à une ligne et des lignes non-une, ainsi que la séparation de la déclaration de contrôle ( for
, if
, qu’est-ce que vous avez) et la fin de la déclaration.
Par exemple:
for (...) { for (...) for (...) { // a couple pages of code } // which for block is ending here? A good text editor will tell you, // but it's not obvious when you're reading the code }
J’avais l’habitude d’être un grand partisan des “accolades sont un MUST!”, Mais depuis que j’ai adopté les tests unitaires, je trouve que mes tests unitaires protègent les déclarations sans frein des scénarios comme:
if (foo) snafu(); bar();
With good unit tests, I can confidently omit curly braces for simple statements to improve readability (yes, that can be subjective).
Alternatively, for something like the above, I would likely inline that to look like:
if (foo) snafu();
That way, the developer who needs to add bar() to the condition, would be more apt to recognize the lack of curly braces, and add them.
Use some personal judgement.
if (foo) bar();
is fine by itself. Unless you’re really worried about morons putting in something like this later:
if (foo) bar(); baz();
If you’re not worried about morons, you’re fine (I’m not — if they can’t get basic code syntax right, this is the least of their problems)>
In exchange, it’s a lot more readable.
The rest of the time:
if (foo) { bar(); baz(); }
Which has been my favorite as long as I can remember. Aditionellement:
if (foo) { bar(); baz(); } else { qux(); }
Travaille pour moi.
Vertical space by itself isn’t terribly relevant, readability is. The opening brace on a line by itself just stops the conversation for a syntactic element, until your eye moves down to the next line. Not what I like.
Let’s say you have some code:
if (foo) bar();
and then someone else comes along and adds:
if (foo) snafu(); bar();
According to the way it’s written, bar(); is now executed unconditionally. By including the curly braces, you prevent this kind of accidental error. Code should be written in such a way as to make such mistakes difficult or impossible to make. If I was doing a code review and saw the missing braces, especially spread across multiple lines, I would create a defect. In cases where it is justified, keep it on one line so that the chance of making such an error is again kept to a minimum.
Reducing lines is not really a good argument for dropping braces. If your method is too big, it should probably be refactored into smaller pieces or restructured. Doing that will no doubt increase readability more than simply taking out braces.
in order to keep the code with braces from taking up lots of space, I use the technique recommended in the book Code Complete :
if (...) { foo(); bar(); } else { ... }
I always omit them when appropriate, such as in your first example. Clean, concise code I can see and understand by glancing at is easier to maintain, debug and understand than code I have to scroll through and read line by line. I think most programmers will agree with this.
It is easy for it to get out of hand if you start doing multiple nesting, if/else clauses and so on, but I think most programmers should be able to tell where to draw the line.
I see it kind of like the argument for if ( foo == 0 )
vs if ( 0 == foo )
. The latter may prevent bugs for new programmers (and maybe even occasionally for veterans), while the former is easier to quickly read and understand when you’re maintaining code.
Most times it is ingrained as a coding standard, whether for a company or an FOSS project.
Ultimately someone else will need to grok your code and it is a major time drain for each developer to have to figure out the specific style of the section of code they are working on.
Also, imagine that someone is going between Python and a Cish language more than once a day… In Python indenting is part of the block symantics of the language and it would be quite easy to make a mistake like the one you quote.
Err on the side of more secure – just one more bug you potentially won’t have to fix.
I personally feel more secure if all of my blocks are wrapped in curlys. Even for one-liners, these are simple notations that easily prevent mistakes. It makes the code more readable in the sense that you clearly see what is in the block as not to confuse the body of the block with the following statements outside of the block.
If I have a one-liner, I typically format it as follows:
if( some_condition ) { do_some_operation; }
If the line is just too cumbersome then use the following:
if( some_condition ) { do_some_operation; }