Skip to content

Coding Standards Part 1 Style

amirroth edited this page Sep 23, 2021 · 20 revisions

Formatting guidelines are not overly strict. The important thing is that code is clear and readable with an appropriate amount of whitespace and reasonable length lines. A few best practices are also mentioned.

Indentation

Tabs are not allowed, and a mixture of tabs and spaces is strictly forbidden. Modern autoindenting IDEs and editors require a consistent standard to be set. In EnergyPlus, we are using 4 spaces per indentation level. Set your IDE appropriately.

int myFunction(bool b) 
{
    if (b)
    {
        // do something
    }
}

[SM] There are good arguments for both tab and space indenting. Tabs have some benefits: 1) User controls indenting they want to see in their IDE, 2) With visual indent set to 3 or above commenting out lines doesn't break indentation alignment (this is very nice!), 3) Files are slightly smaller and thus should be very slightly faster to compile.

[JT] Consistency is the most important thing here. Tabs seem to have stuck at this point, so that is where we are

Code Blocks and Braces

Code blocks must be enclosed by braces, i.e., {}. C/C++ allow one-line code blocks to be used without braces, but this can sometimes lead to hard-to-find bugs. So braces it is.

// Bad Idea
// this compiles and does what you want, but can lead to confusing errors if close attention is not paid.
for (int i = 0; i < 15; ++i)
    std::cout << i << std::endl;

// Much better and readability is not impacted
// It's clear which statements are part of the loop (or if block, or whatever)
for (int i = 0; i < 15; ++i) {
    std::cout << i << std::endl;
}

Line Length

Keep lines to a reasonable length.

// Bad Idea: hard to follow
if (x && y && myFunctionThatReturnsBool() && caseNumber3 && (15 > 12 || 2 < 3)) { 
}

// Good Idea: logical grouping, easier to read
if (x && y && myFunctionThatReturnsBool() 
    && caseNumber3 
    && (15 > 12 || 2 < 3)) { 
}

[SM] Converted code is currently unwrapped pending decision on line wrapping. Since IDEs can soft-wrap for you one option is to leave lines unwrapped and let the user control visual wrapping to make best use of their display and preferences. Wrapping lines is hard to do nicely and some editors (looking at you, emacs!) do silly things with aligning wrapped lines on function parentheses that creates a maintenance burden.

Comments

Comment blocks should use //, not /* */. Using // makes it much easier to comment out a block of code while debugging.

// this function does something
int myFunc()
{
}

To comment out this function block during debugging we might do:

/*
// this function does something
int myFunc()
{
}
*/

which would be impossible if the function comment header used /* */.

Comments and Braces

For large code blocks, it's good to add a comment to the closing brace to identify the code block that it is closing. Here are some examples.

int myFunction() 
{
    for (int i = 0; i < max_i; ++i) {
        for (int j = 0; j < max_j; ++j) {
            for (int k = 0; k < max_k; ++k) {
                if (array[i*max_k*max_j + j*max_k + k] > 0) {
                    // do a bunch of stuff






























                } // if (array[] > 0)
            } // for (k)
        } // for (j) 
    } // for (i)
} // myFunction

Isn't that better?

Initialize Member Variables

...with the member initializer list

// Bad Idea
class MyClass
{
public:
  MyClass(int t_value)
  {
    m_value = t_value;
  }

private:
  int m_value;
};


// Good Idea
// C++'s memeber initializer list is unique to the language and leads to
// cleaner code and potential performance gains that other languages cannot 
// match
class MyClass
{
public:
  MyClass(int value)
    : m_value(value)
  {
  }

private:
  int m_value;
};

Clone this wiki locally