-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
oF Code Style
Two concepts overlap in the "style": (1) whitespace / indentation / bracing and (2) concepts like variable naming.
To simplify whitespace and bracing management, in 2023 a .clang-format file has been adopted, greatly simplifying the formatting process. The starting point was the 'webkit' template, from which a few tweaks managed to conform to almost all specificities of the current code.
As a result of that, the styling guide has been simplified. The .clang-format itself can be referred to as the whitespace styling reference but should simply be executed to conform the code (there are many ways to execute clang-format, from the command line, within IDE's, or even within git.); the main points :
-
Use tabs for indentation (not spaces) and set your tab width to 4 spaces. Keep in mind the Github source code viewer uses a tab width of 8 spaces by default; you can change this in your Github Settings.
-
Indent blocks inside preprocessor definitions
#ifdef WIN32
#define IS_WIN32
#endif
- The
public
,protected
, andprivate
keywords should not be indented inside the class
class myClass{
public:
myClass();
void aFunction();
};
- Pointers or references as well as binary operators use a space on each side:
Correct | Wrong |
char * x;
const QString & myString;
const char * const y = "hello";
int a = b + c;
|
char* x;
const QString &myString;
const char* const y = "hello";
int a = b+c;
|
- The left curly brace goes on the same line as the start of the statement.
Correct | Wrong |
if (codec) {
// do something
}
|
if (codec)
{
// do something
}
|
But again, all the above should be mechanically processed by clang-format and should not take specific attention.
NOTE: A decision was made not to "blanket-reformat" the codebase as even though git is not bad in ignoring whitespace, it does cover the history with a "reformat" commit. In order to prevent that, the formatting is applied as other changes are occurring in files, so the (squashed) commit message is relevant to function/implementation and not formatting.
These are the things that are not covered by the clang-format operation:
- Declare each variable on a separate line
- Avoid short (e.g.
a
,rbarr
,nughdeget
) names whenever possible - Single character variable names are only okay for counters and temporaries, where the purpose of the variable is obvious
Correct | Wrong |
int height;
int width;
char * nameOfThis;
char * nameOfThat;
|
int a, b;
char * c, * d;
|
- Variables and functions start with a lower-case letter. Each consecutive word in a variable’s name starts with an upper-case letter (camel case).
Correct | Wrong |
int thisIsAnImportantInteger;
|
int thisisanimportantinteger;
|
- Avoid abbreviations
Correct | Wrong |
short counter;
char itemDelimiter = '\t';
|
short Cntr;
char ITEM_DELIM = '\t';
|
- OF Core class names start with "of". eg ofTexture. Addon authors are encouraged to use the "ofx" prefix.
Correct | Wrong |
class ofCoolClass {
...
|
class OFCoolClass {
...
* Use parentheses to group expressions:
```cpp
// Wrong
if(a && b || c){
// do something
}
// Correct
if((a && b) || c){
// do something
}
// Wrong
int d = a + b / c;
// Correct
int d = (a + b) / c;
// Wrong
/*
Yo.
This is
a multiline comment.
Peace.
*/
// Correct
//
// Yo.
//
// This is not
// a multiline comment.
//
// Peace.
// We prefer clear code to clever code - ideally it can be both.
// ie inside ofImage.cpp
// Wrong
ofLog(OF_LOG_WARNING, "couldn't load image");
// Correct
ofLog(OF_LOG_WARNING, "ofImage: couldn't load image");
Don't use ternary operators (i.e. Don't use while loops if possible. Use for loops for simple cases and iterators for more complex iteration. Use vectors unless there is a strong reason not to. When developing new code, you are encouraged to use const arguments and const methods wherever possible with the exception of return types. If you need a const return type, you must also provide a non-const version. From the user's perspective, we encourage const guarantees, but not const requirements. In general, do not create a situation that forces the user to be aware of const. We currently prefer that const is only added to existing code as needed, in accordance with the above guidelines. We don't do this in the core. If you need it for initializing a reference then use it but otherwise do your initialization in the constructor.
Please don't use assert. We will find you and and make you pay! :) Please don't use exceptions. Print a warning or an error and clean things up instead. If you are using a library that uses exceptions, make sure to catch and print the errors so exceptions are not thrown in user code.
Please use
// We don't do this:
#define OF_IMAGE_QUALITY_BEST 0
#define OF_IMAGE_QUALITY_LOW 1
class ofImage {
…
void setQuality(int quality);
…
};
//--------------------------------------------------
// We do this:
enum ofImageQualityType {
OF_IMAGE_QUALITY_BEST,
OF_IMAGE_QUALITY_LOW
};
class ofImage {
…
void setQuality(ofImageQualityType qualityType); // use this
…
};
void testApp::setup() {
…
myImage.setQuality(OF_IMAGE_QUALITY_BEST);
…
} |