📜 ⬆️ ⬇️

Do you know all about if?

How do you put brackets, what do you include in blocks, how do you write logical expressions? .. Do you think that by following simple rules, you can not only make the code more readable, but also make debugging easier, improve diagnostics, and improve performance? ..

I offer 5K thoughts and links to style guides (hereinafter SG). I hope that this article will be a pleasant and easy reading. And I am sure that it does not touch all the issues and I hope for a substantive discussion.


Strictly speaking, such things can be written not only about if. It is if that is chosen almost by accident (in the end, and why not?). The idea of ​​this article threw f0b0s . She (the idea) was supported by several people at once, I also began to wait for the article; but without waiting, he decided to raise this banner himself. f0b0s , thanks for the idea, I apologize, if ahead, wait for comments.
')
For completeness, we will devote a second to banal things.

Braces


Ideal option to write curly brackets everywhere, and each expression if / else / else_if

  // OK
 if (a == b) {
   foo ();
 } else {
   bar ();
 } 

some SGs recommend writing else on a new line

  // Not
 } else {
 // but
 }
 else {
 // or
 }
 else
 { 

Then else it turns out with the same indent, as corresponding if. But there is no unity in this matter.

If you, nevertheless, omit the brackets (in which there is no crime), then you need to take into account two aspects. First, stick with the same tactics for if and else blocks:

  // smarter
 if (a == b) {
   foo ();
   bar ();
 } else
   bazzz (); 

And, secondly, do not write the entire if in one line.

  // VERY BAD
 if (cond ()) act ();
 else err (); 

Mixing styles within one if / else makes it difficult to read, and placing several expressions on one line also makes debugging difficult; in the last example, cond () and act () are located on the same line; This makes it difficult to find errors by deadline and debugging.

And two more comments about the blocks


Create variables only when needed


Take advantage of C ++. If a variable is needed only in a block, then create it only in a block.

  // BADLY
 SomeClass p;  // needed only in block
 if (x == y) {
   p.moveTo (x, y);
   p.logResultsOfMovement ();
 } 

  // OK
 if (x == y) {
   SomeClass p;  // needed only in block
   p.moveTo (x, y);
   p.logResultsOfMovement ();
 } 

This will save processor time, memory ... in general, everything that is so dear to every person professing humanistic ideals :-)

Describe the normal course of events first.


In the if / else expressions, first describe the normal course of events, and in the else block, handle the handling of abnormal situations. This makes it easier to read the program:

  // OK
 bool errorFlag = openConnection ();
 if (! errorFlag) {
   doJob ();
 } else {
   dropJob ();
 } 

Boolean expressions


C ++ not C


First of all, in C ++ you should not follow the style of C to write

  // BADLY
 if (float_num) {}
 if (int_num) {} 

The C ++ standard does not guarantee that float (0) and even int (0) are implemented as “all bits 0” (although this works, of course, but this is purely coincidental :-)).

If you need to check for equality 0, then it is better to write this:

  // OK
 if (float_num! = .0) {}
 if (int_num! = 0) {} 

As a condition, only logical values ​​should be used. This, incidentally, also applies to cycles:

  // OK
 while (true) {}
 // BADLY
 while (1) {}
 for (;;) {} 

Separate logical expressions


If a logical expression consists of several parts, then the worst practice is to write them all in a heap. Is it possible to quickly understand what is written here?

  // BADLY
 if (figureX> leftLimit && figureX <fightLimit && figureColor == GREEN) 

Illumination, of course, would help, but without illumination the following expression reads much simpler:

  // OK
 if (figureX> leftLimit &&
     figureX <fightLimit &&
     figureColor == GREEN) 

But absolutely perfect, introduce additional variables into the program.

  // VERY CUTE
 bool isInside = figureX> leftLimit && figureX <fightLimit;
 bool isGreen = figureColor == GREEN;
 if (isInside && isGreen) 

This program is much easier to read, and in addition, the variables isInside and isGreen can be useful in the future.

And for greater readability, you can put brackets around logical expressions in the first two lines.

Expressions in terms of


It is better to make expressions from conditions

  // OK
 bool dataReaded = readDdata (fileName);
 if (dataReaded) {} 

This makes the code more readable than

  // BADLY
 if (readDdata (fileName)) {} 

In addition, it echoes the general idea of ​​the possibility of unloading the logical expression that has already been expressed above.

And, of course, “each expression has its own string!”.

  // VERY BAD
 if (readDdata (getFileNameFromArray (getEnvAsArray ()))) {} 

Again, it is difficult to read, difficult to debug, difficult to localize errors.

Assignments to


For the reasons already stated, it is better not to make assignments in logical expressions:

  // BADLY
 if (lid = getLabel () == curentLabel ()) 

This leads to many troubles. The expansion of a logical expression, placing multiple calls in one line. The appearance of two similar (externally) operators "=" and "==", which additionally complicates reading and increases the likelihood of errors and typos.

A very common mistake is to write one "=" instead of two ("=="). So that the compiler immediately pulled you by the hand, some people develop the habit of writing comparisons on the contrary (I confess, I could not work it out in myself :-))

If not write

  // BADLY?
 if (x == 1) 

but

  // OK?
 if (1 == x) 

then you can not be afraid to type and write "=" instead of "==". In a good version, the program simply does not compile if you make such a typo.

It seems not forgotten


If you forgot something, thanks for the comments :-)

A pair of good SG:

Classic SG . Pay attention to the links below - there are even more extensive documents.

SG from Google . It is worth exploring, as it is not completely in solidarity with the aforementioned SG.

upd Thanks to all who commented! The discussion (as I expected) turned out to be more interesting than the article :-) I do not comment on the article for two reasons. Many remarks (equally fair) contradict each other (which is not surprising when discussing such topics). And second, if I make all the edits, the discussion will become completely incomprehensible and the article will lose its best part :-) Let everything remain as it is and the “errors” (?) Made in the article will become an illustration to the discussion.

Source: https://habr.com/ru/post/61323/


All Articles