1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
#
# $XORP: xorp/devnotes/coding-style.txt,v 1.6 2007/05/23 12:12:33 pavlin Exp $
#
Provisional XORP C++ coding style
This is a *provisional* attempt to lay down some rules that we can
adhere to and moan about. The style is only intended to apply to new
code, not code that we import. Hopefully, the style is equidistant
from our default coding styles that all are equally peturbed.
- DOCTRINE
Ignore any section of this document when doing so would enhance
readability. Feel free to edit someone else's code into agreement
with these principles, or into agreement with your own variant of
these principles. Expect that your code may be likewise edited.
- FILE PROLOGUES
Files should have a prologue containing the copyright, a description
of what the file does, an RCS version id, and an RCS
string/identifier in implementation files that ident(1) can use.
We have a standard templates to work from:
devnotes/template.hh
devnotes/template.cc
devnotes/template.h
devnotes/template.c
- INDENTATION
Use 4 spaces per indent level. Indentation should generally follow
"gnu". The default emacs c/c++ style is gnu, can be set with
M-x c-set-style gnu).
- BRACES
Try to avoid gratuitous newlines between statements opening a brace
and the opening brace. E.g., prefer:
if (abc == 3) {
/* XXX */
}
to:
if (abc == 3)
{
/* XXX */
}
For the sake of readability, try to place white space either side of
braces. E.g., prefer:
bool foo() { return _some_value; }
to:
bool foo() {return some_value;}
- REFERENCE AND POINTER ANNOTATIONS
Prefer:
foo(int& x) and bar(int* y)
to:
foo(int &x) and bar(int *y)
The former appears to be more widely used in C++ literature and so we go
with this for the sake of consistency.
- TEMPORARY REFERENCES
Temporary references can help make code more readable. When used
with containers to pointer types the resulting code can be more
readable and efficient.
static void process(const string& s); // Forward declaration
static void
process_long_names1(list<string*> names)
{
list<string*>::const_iterator ci;
for (ci = names.begin(); ci != names.end(); ++ci) {
if ((*ci)->size() > 10) { // Direct use of iterator
process(*(*ci));
}
}
}
static void
process_long_names2(list<string*> names)
{
list<string*>::const_iterator ci;
for (ci = names.begin(); ci != names.end(); ++ci) {
const string& s = *(*ci); // Use of temporary ref
if (s.size() > 10) {
process(s);
}
}
}
- COMMENTS
Use // for comments.
Avoid obvious comments inside routines. Any comments inside routines
should be short -- one line, when possible. Prefer single blank
lines for separating sections of code.
- API DOCUMENTATION (kdoc)
All major routines should have a comment briefly describing what
they do. We use kdoc comments (similar to javadoc) to generate API
overviews and programming documentation.
- TERMINAL WIDTH
Assume the terminal is 80 characters wide. Sure there'll be odd
times when wraps cannot be avoided, but gratuitous wrapping will
give you a "wide boy" reputation.
- CAPITALIZATION
class Wrench {
public:
Wrench() { ... };
~Wrench() { ... };
apply_force();
...
private:
double _weight;
};
Note that the class's public interface comes first.
- UNDERSCORING
Member variables should begin with an underscore. Regular variables
and function names should separate words with underscores.
Double underscores should never be used, they are often used by the
compiler during name munging.
- NAMES FOR MODIFIERS AND ACCESSORS.
Often, a private member variable will have associated public member
functions that get and/or set its value. If the variable is named
"_xxx", name the getter function "xxx()" and the setter function
"set_xxx()". The getter function should generally be const.
- STRING METHODS
When necesary to have a string method, call it str(). In general, try
to avoid adding operator string().
- BOOL METHODS
In general, always avoid adding operator bool(), unless there is a
strong reason for adding it.
- METHOD DEFINITIONS
When defining C++ in implementation files place the return value
and class/method declarations on separate lines. E.g.,
const char*
LuckyEightBall::speak() const
{
// blah blah
}
- ABBREVIATIONS
Should be avoided, especially in method names.
- INTEGER TYPES
Use integer types defined in inttypes.h, these are POSIX compatible
and portable.
- USE OF CONST
Decorate member functions with "const" whenever appropriate for
purposes of documentation. Member functions that do not alter an
object's value should be "const". Sometimes, a member variable is
altered by a function that does not conceptually change the object's
value. Mark such member variables as "mutable" to enhance the
applicability of "const".
- USE OF EXCEPTIONS AND STANDARD TEMPLATE LIBRARY
Non-kernel modules should use exceptions and the standard template
library where appropriate.
- USE OF AUTOCONF
We will use GNU autoconf to improve portability. The "xorp_config.h"
header file will define symbols specifying system properties that
may differ between reasonable Unices. This file is included by
"libxorp/xorp.h" which itself includes and defines a number of other
useful header files and features. The first file included by any XORP
source file should be "libxorp/xorp.h".
However, if one of the included header files is the module-specific
"foo_module.h" (required by "libxorp/xlog.h"), that file should
be included before "libxorp/xorp.h".
- INCLUDE FILES
Include files should be sorted into domain, each domain separated by
a blank line:
"foo_module.h"
"libxorp/xorp.h"
kernel includes
sys includes
net includes
default include path includes
XORP libraries includes
local includes
Don't sweat it too hard, however.
- SPACES AND PARENTHESES
Binary operators should have spaces around them to ease
decipherment. Parentheses have to used when precedence dictates and
can be used to reduce confusion, particularly with long
expressions. Do not put spaces around parentheses.
Keywords should likewise have spaces around them. For example,
`if (x)', not `if(x)'; and `return x', not `return(x)'.
- VARIABLE DECLARATIONS
Place variable declarations at the beginning of the relevant
scope. This includes placing declarations in the middle of
functions, close to their first uses, when appropriate. Declare
iteration variables inside the `for' statement when possible; this
is most of the time. Declare a test variable inside the `if' test
when possible; this happens comparatively rarely. Prefer multiple
declarations when defining several variables that require
initializers.
- PORTABILITY
All IPv6-specific code should be "#ifdef HAVE_IPV6" :
#ifdef HAVE_IPV6
....
#endif // HAVE_IPV6
If there is only one line of code between #ifdef and #endif, then
do not add the comment after "#endif".
|