-
Notifications
You must be signed in to change notification settings - Fork 514
Coding style
Some rules for writing code in BOINC. In general:
- Make the code short and simple.
- Split up long functions.
- Imitate the style and structure of code that's already there, even if you don't like it.
- If you're writing a function that might be of general utility, make it general, and put it in lib/ or html/inc. Check first - it might already be there.
- Don't copy and paste code. Use functions.
Most functions should return an integer error code. Nonzero means error. See lib/error_numbers.h for a list of error codes. Exceptions:
- PHP database access functions, which use the mysql_* convention that zero means error, and you call mysql_error() or mysql_error_string() to find details.
- Functions that return whether a condition holds;
such functions return bool and should have descriptive names like
is_job_finished(). - Functions that return a number or other type, and for which no errors are possible.
Calls to functions that return an error code should check the code. Generally they should return non-zero on error, e.g.:
retval = blah();
if (retval) return retval;Don't use exceptions.
- All files have a comment at the top saying what's in the file (and perhaps what isn't).
- Functions are preceded by a comment saying what they do.
- structs and classes are preceded by a comment saying what they represent.
- Names are descriptive without being verbose (local variables names may be short).
- Class and type names, and
#definedsymbols, are all upper case, with underscores to separate words. - Variable and function names are all lower case, with underscores to separate words.
- No mixed case names.
- Each level of indentation is 4 spaces (not a tab).
- Multi-line function call:
func(
blah, blah, blah, blah, blah,
blah, blah, blah, blah, blah
);-
switchstatements:caselabels are at same indent level asswitch
switch (foo) {
case 1:
...
break;
case 2:
...
break;
}- Opening curly brace goes at end of line (not next line):
if (foobar) {
...
} else if (blah) {
...
} else {
...
}- Always use curly braces on multi-line
ifstatements.
if (foo)
return blah; // WRONG- 1-line
if()statements are OK:
if (foo) return blah;- There should be few numeric constants in code. Use defined symbols instead. Put the defines at the top of the file or in the appropriate include file.
- For C++ and PHP, use
//for all comments. - End multi-line comments with an empty comment line, e.g.
// This function does blah blah
// Call it when blah blah
//
function foo() {
}The range-based for statement, introduced in C++ 11, replaces
for (unsigned int i=0; i<results.size(); i++) {
RESULT& r = results[i];
...
}with
for (RESULT& r: results) {
...
}PHP has an analogous foreach statement.
Use range-based for where possible, because
- it's shorter and easier to read.
- it eliminates bugs where i is inadvertently modified in the loop
Another readability issue:
bool SOME_CLASS::check(char *x) {
for (unsigned int i=0; i<items.size(); i++) {
if (!strcmp(items[i].name, x)) {
...where the vector 'items' is a member of SOME_CLASS. The problem: this code doesn't show the type of the list items; you have to look at the .h file. A range-based for shows you the type (ITEM in this case):
bool SOME_CLASS::check(char *x) {
for (ITEM& item: items) {
if (!strcmp(item.name, x)) {
...Notes:
-
Sometimes you need a loop counter. In that case you can either use the original for syntax, or use a range-based for and add your own counter.
-
If you're going to delete items in the list, don't use a range-based for; use your own vector iterator.
-
C++ lets you use 'auto':
for (auto& r: results) {
...
}but avoid this because it hides the type of r, making the code harder to understand; avoid 'auto' in general for this reason.
- C++
.hfiles often contain both interface and implementation. Clearly divide these.
- A
.cppfile should have the minimum set of #includes to build that particular file (in particular, the includes needed byfoo.cppshould be infoo.cpp, notfoo.h). -
foo.cppshould includefoo.h - For readability, includes should be ordered from general (
<stdio.h>) to specific (foo.h). However, this order shouldn't matter.
-
foo.hshould haveexterndeclarations for all public functions and variables infoo.cpp. There should be noexternstatements in.cppfiles.
- If a function or variable is used in only its same file, declare it
static.
- Avoid operator and function overloading.
- Avoid templates.
- Avoid stream I/O; use printf() and scanf().
- Use
typedef(not#define) to define types. - Don't use
memset()ormemcpy()to initialize or copy classes that are non-C compatible. Write a default constructor and a copy constructor instead. - Avoid dynamic memory allocation. Functions shouldn't return pointers to malloc'd items.
struct FOO {
...
};You can then declare variables as:
FOO x;Comment out blocks of code as follows:
#if 0
...
#endifPHP scripts should output "HTML 4.01 Transitional". The HTML should pass the W3C validator. This means, e.g., you must have quotes around attributes that have non-alpha characters in them. However, all-alpha attributes need not have quotes, and tags like <br> and <p> need not be closed.
The HTML need not be XHTML.
This means no self-closing tags like <br />.
Do not access $_POST or $_GET directly.
Use get_int(), get_str(), post_int() and post_str() (from util.inc) to get POST and GET data.
- Use the database abstraction layer.
- If a POST or GET string value will be used in a database query, use
BoincDb::escape_stringto escape it.