wiki:CodingGuidelines

Version 36 (modified by jinmei, 8 years ago) (diff)

--

This page documents some coding guidelines.

Refer also to the BIND 9 coding guidelines. They should be used where they do not conflict with the guidelines on this page.

  1. Common
    1. Testing/Documentation addresses and prefixes
    2. XXX vs. TODO Comments
  2. Python Style
    1. Class initializers
  3. C++ Style
    1. File Name Conventions
    2. Ordering Include Files
    3. Tabs & Indentation
    4. Curly Braces
      1. Curly Braces for Catch
    5. Operator Overloading
    6. Class Attributes
    7. Non-copyable Classes
    8. Naming
    9. Where to Put Reference and Pointer Operators
    10. Comments
      1. Doxygen Comment Style
      2. Explicit \brief for Doxygen
    11. Methods
    12. Namespaces
    13. Consts
    14. Google Test Style
  4. User Interface (UI) Guidelines
    1. IP address and port formatting
  5. Imported Code
  6. Guidelines Adopted by Other Projects
  7. About this Document

Common

Testing/Documentation addresses and prefixes

Use 192.0.2.0/24 and 2001:db8::/32 for purposes like addresses used in test cases or examples in documentation. Likewise, use reserved example domain names such as example.com, .test, .example, etc for domain names used in these cases. They are reserved by specifications and should be the safest in terms of collision avoidance.

XXX vs. TODO Comments

We sprinkle comments in code with keywords to indicate pending work. De-facto standards are either XXX or TODO.

In BIND 10, TODO is preferred.

XXX comments that do not refer to potential future changes or improvements should just be comments.

Python Style

For Python coding, we will use the Python style guidelines:

http://www.python.org/dev/peps/pep-0008/

Class initializers

In Python, the __init__() method should be the first one declared in a class definition, like this:

class foo:
    # constructor definition here
    def __init__(self):
       ...
    # other functions may follow
    def bar(self):
       ...

C++ Style

File Name Conventions

Use .cc for C++ source files. This is basically a mere preference and to ensure consistency throughout the package.

Use .h for C++ header files. This is because we may want to provide a C-callable wrapper for some APIs, and some C++ header files are to be included in a C source file. In that case C-compatible file names will look more natural.

Use all all-lowercase characters for file names. This is consistent with the current recommendation for python, and so it will make the file name convention consistent throughout the BIND10 source tree. Not mixing lower/upper cases will also help avoid name conflicts in a case insensitive file system. Note that this policy may not compatible with C++ class name convention (see below) if the file name is based on the class name (e.g., name "myclass.cc" for the definition of the "Myclass" classs). We explicitly accept the conflict, but note that this means it will effectively prohibit mixing cases in class names ("Myclass" and "MyClass" may not coexist).

Ordering Include Files

We include our own project headers first, then library, and finally system headers, whenever possible. Each header is expected to have any necessary #include statements it needs, and this helps insure that.

#include <dns/message.h> 
#include <boost/shared_ptr.hpp>
#include <string>

Tabs & Indentation

Do not use hard tabs. (Commits may be prevented by a Subversion pre-commit hook.)

Indentation at each level is 4 spaces for C++ and Python, other languages should use what is "usual and expected."

In C++ we use the BSD style (also from BIND 9), where continuing lines are aligned with the corresponding opening parenthesis, like this:

if (JS_DefineProperty(cx, o, "data",
                      STRING_TO_JSVAL(JS_NewStringCopyN(cx, data, res)),
                      NULL, NULL, JSPROP_ENUMERATE) != 0) {

Curly Braces

Always add braces even for a single-line block:

if (something_holds) {
    perform something;
} else if (nonorthogonal_condition) {
    perform otherthing;
} else { // optionally comment to clarify the fully orthogonal case
    perform finalthing;
}

Curly Braces for Catch

A catch statement should have braces on a single line, like this:

     .
     . 
     .
   } catch (const SomeException& ex) { 
     .
     .
     .

Operator Overloading

When a class supports operator overloading, then there should also be non-overloaded methods, like this:

class Foo {
public:
    bool equals(const Foo &other) const;
    bool operator==(const Foo &other) const { return (equals(other)); }
}

Class Attributes

Accessors for class attributes should be called getXxx().

Mutators for class attributes should be called setXxx().

(where xxx is the attribute)

Non-copyable Classes

If you want a class to be non-copyable (neither copy constructor nor assignment), inhert from boost::noncopyable rather than implementing this yourself.

http://www.boost.org/doc/libs/1_47_0/libs/utility/utility.htm#Class_noncopyable

Naming

Don't start things with underscores. According to Stroustrup's C++ book:

Names starting with an underscore are reserved for special facilities in the implementation and the run-time environment, so such names should not be used in application programs.

Class names are LikeThis, methods are likeThis(), variables are like_this, and constants are LIKE_THIS. Data class members are like_this_.

Enumerations are written as

enum EnumName {
  FOO,
  BAR
} enum_instance;

Note that unless you have a specific reason to set specific values, leave specific values off. These can be written if needed:

enum ExamplePortNumbers {
  DNS = 53,
  DHCP = 68
};

Where to Put Reference and Pointer Operators

In C++, it seems to be more common to not insert a space between the type and the operator:

int* int_var;
int& int_ref;

Comments

Multiline comments can be written in C++ or C style (that is, with or /* */ marks).

/*
 * This is a comment.  It is important probably.
 */
//
// This is a comment.  It is important probably.
//
/* This is also ok. */

// As is this.

Comments at the end of lines should usually be C++ style:

class Foo {
    int bar_length;  // The length of the bar in millimeters.
};

Doxygen Comment Style

When writing a Doxygen special comment block there are several possible styles:

http://www.stack.nl/~dimitri/doxygen/docblocks.html

We use the C++ style of 3-slashes:

/// A lot of examples are called foo().
///
/// \param baz foo() usually takes an argument
void foo(Bar baz) {
    ...
}

Explicit \brief for Doxygen

If you don't use \brief as the first thing in your doxygen comment, then doxygen will turn the first paragraph into a \brief description anyway. However, we include it anyway so that everybody understands that this is the \brief description.

Methods

For methods where the arguments all fit on one line with the curly brace, it should be written on one line:

int
methodName(int argument_one, std::string message) {
    ...
}

Where this is not possible the curly brace should go on a line by itself:

int
methodName(int argument_one, std::string message,
           int another_argument)
{
    ...
}

Namespaces

Namespaces will be lower case: isc::dns, or isc::cc.

using namespace should never be used in a header file. They may be used in .cc source files.

Consts

Use const as much as possible. Make class methods const member functions whenever possible.

If a function has a parameter with a "top-level const", make sure the const appears not only in the definition but also in the declaration. For example, if you define the following function in a .cc file:

int
foo(const int param) {
...
}

then make sure the const appears in the corresponding declaration in a header file (.h):

int foo(const int param);  // const cannot be omitted

Technically, the latter const is redundant. But SunStudio C++ compilers have a bug in name mangling that requires the "consistency": http://developers.sun.com/sunstudio/documentation/ss12/mr/READMEs/c++.html#cNameMangling

Unfortunately, we want to be as portable as possible, and so need to work around this by being redundant.

Google Test Style

Try to use EXPECT_<op>() rather than EXPECT_TRUE():

EXPECT_TRUE(run_time > 1);   // BAD

EXPECT_GT(run_time, 1);      // Good

because when the test fails the latter will provide more detailed information (the values of "actual" and "expected").

Note that this is not always possible, especially when checking an object that has no operator<<() (or more obviously no operator<op>()), which is used to output on failure.

User Interface (UI) Guidelines

BIND 10 is a server process, so does not have much that would be considered a user interface. This section discusses what we do have.

IP address and port formatting

Whenever an IP address and port is output, IETF RFC 2396 and RFC 2732 should be followed.

For IPv4 addresses, this looks like this:

192.0.2.1:53

For IPv6 addresses, this looks like this:

[2001:db8::1]:53

Imported Code

If you import code from another project, try to continue the style of the imported project if changes need to be made. This is for two reasons, one is to make merging future versions easier. The other is the encouragement of submitting changes upstream.

Guidelines Adopted by Other Projects

About this Document

Creation author and date unknown
Reviewed 2011-09-12
Review scheduled 2012-03-12