This guide describes the coding style that I developed over the years. My style isn't verry widespeard. As a matter of fact, I don't know anyone who comes even close to the weird way I program. But I like it and want to share it with you anyway (you lucky bastard!). I use it for all kinds of programming languages: C, C++, Java, C#, Python,... .
If you just want a quick overview of the style, scroll to the bottom of this page and see how some sourcecode was rewritten to my deWiTTERS Style, this should give you an quick idea of how nice it all looks.
Every programmer uses some sort of style, some good, some terrible. A coding style can give code a uniform look. It can make algorithms more clear or more complex. There are 2 main reasons for a certain coding style:
I tried to capture the most important aspects of coding style in the following rules.
Make everything as simple as possible, but not simpler.As a programmer you must always try to respect the above rules, even if you don't follow my style of coding.
Writing understandable and readable code became possible with the birth of modern programming languages. The days when programming was entirely done in assembly are long past us. Therefore my style tries to be as closely to our natural language as possible. You can almost say my code reads like a book. This is probably also the reason why my code is badly documented. I hardly document at all! I even consider documenting as "bad" (and not in the cool sense of the word). Only when I do something weird I add a comment to explain why. In my humble opinion, comments should never say what your code does, let your code say what it does.
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.Martin Fowler
Let's start with the most important topic of coding style: identifiers. All identifiers and the rest of your code and comments should be written in English. It is not unusual that software projects shift from one person to another, from one company to another one, located at the opposite side of the world. So since you never know where your code is going to be next, write all in english.
Variable names should be all lowercase with the words seperated by underscores. It resembles our natural writing the most and therefore it is the most readable. The underscores just replace the spaces in our normal way of writing. A variable called "RedPushButton" cannot be read as easely and as fast as "red_push_button", thrust me.
If you want the variables to be understandable, you must give them obvious names. It is clear that variables all represent some kind of "object" or "value", so name them accordingly. Please don't waste your time with jkuidsPrefixing vndskaVariables ncqWith ksldjfTheir nmdsadType because it just isn't understandable or clean. If you have a variable "age" it's clear that it's an int or unsigned short. If it is "filename", well then it must be a string. Easy! Sometimes for some variables it is more understandable if you include the type in it, for example for gui buttons like "play_button" or "cancel_button".
There are some pre- and postfixes that can increase the readability of your variables. Here follows a list of the most common ones:
Arrays or other variables that represent lists must be written in plural, like enemies, walls and weapons. However, you don't have to do this for all array types since some arrays don't really represent a list of items. Some examples of these are "char filename[64]" or "byte buffer[128]".
Consts or finals must always be written in UPPERCASE, with the words seperated by underscores to make them readable, like MAX_CHILDREN, X_PADDING or PI. This use is widespread and should be used to avoid any confusion with normal variables.
You can use MAX and MIN in your constant names to represent value limits.
Types define the classification of variables. It is a rather abstract term, so we cannot use the english language as a reference on how to write them. But we should definitely make an obvious distinction between them and other identifiers. So for types, I use UpperCamelCase. For every class, struct, enum and other things you can put in front of your variable declarations, use UpperCamelCase.
Name your types in such a way that you can use the same name for generic variables, for example:
HelpWindow help_window;
FileHeader file_header;
Weapon weapons[ MAX_WEAPONS ];
There are a few ways to write if statements. Let's start with the braces. There are 3 mayor ways to place your braces:
if(condition)
if (condition)
if( condition )
I have never seen an english text where braces are
placed like the first example, so why should we code
like that? The words are just not properly seperated.
The second example puts the braces with the condition
instead of the if statement, while the braces are
actually part of the if statement and not the
condition, so the last example is the best. The last
one also has the advantage that one has a better
overview over the braces structure.
if (!((age > 12) && (age < 18)))
if( !((age > 12) && (age < 18)) )
Personally I would write this code differently, but
it's just to show you an example.
Now what to do with the curled braces? Don't use them! Unfortunately C, C++, Java or C# don't allow this, only Python does. So we can't just drop them, but what we can do is place our braces so it looks like a Python program, simple and clean:
if( condition ) {
statements;
}
else if( condition ) {
statements;
}
else {
statements;
}
When conditions get too long, you'll have to split the line. Try to split it up before an operator and where conditions are leastly related. Align the next line with the previous one and use indentation to reveal the nested structure. Don't put the curled brace right behind the condition, but in this case put it on the next line to make the subblock clear.
if( (current_mayor_version < MIN_MAYOR_VERSION)
|| (current_mayor_version == MIN_MAYOR_VERSION
&& current_minor_version < MIN_MINOR_VERSION) )
{
update();
}
When there is only one statement after the if condition, you can skip the curled braces, but make sure you put the statement on the next line, unless it is a return or a break.
if( bullet_count == 0 )
reload();
if( a < 0 ) return;
While loops are written the same as if structures. I use 4 spaces for every indentation.
while( condition ) {
statements;
}
For do-while loops, put the while at the same line as the closing bracket. This way there is no confusion if it is a while at the end or the beginning of a subblock.
do {
statements;
} while( condition )
for-loops' one and only purpose in life is iteration. It's what they do! for-loops can always be replaced with while-loops, but please don't do that. When you iterate over some elements, try using 'for', and if it really doesn't work out, use a 'while'. The 'for' structure is pretty straight forward:
for( int i = 0; i < MAX_ELEMENTS; i++ ) {
statements;
}
Use i, j, k, l, m for iterating over numbers and
'it' for iterating over objects.
Switch statements have a similar structure to if and while structures. The only thing you have to consider is the extra indentation. Also leave an extra space right behind the break.
switch( variable ) {
case 0:
statements;
break;
case 1:
statements;
break;
default:
break;
}
Functions do things, and their name should make this clear. Therefore, always include a verb in it, no exceptions! Use the same naming as with variables, this means all lowercase words seperated by underscores. This allows you to make nice little sentences in your code that everyone can understand.
Also make sure the function does what the name says it does, no more, no less. So if you have a function called "load_resources", make sure it only loads resources and doesn't do any other init stuff. Sometimes you get tempted by quickly initializing things in the load_resources because you already call it from a higher level, but this will only get you into trouble later. My deWiTTERS Style uses verry few comments, so a function should definitely do what it's name says it does. And when a function returns something, make sure it is clear from it's name what it returns.
Some functions come in "yin and yang" pairs, and you should be consistent with your naming. Some examples are get/set, add/remove, insert/delete, create/destroy, start/stop, increment/decrement, new/old, begin/end, first/last, up/down, next/prev, open/close, load/save, show/hide, enable/disable, resume/suspend, etc.
Here follows a simple function call. Use a space right after the opening brace and right before the closing brace, just as with if structures. Also leaver a space right after the comma, like done in the english language.
do_something( with, these, parameters );
When function calls get too long, you'll have to split it up in several lines. Align the next lines with the previous so the structure gets obvious, and break after the comma.
HWND hwnd = CreateWindow( "MyWin32App", "Cool application",
WS_OVERLAPPEDWINDOW,
my_x_pos, my_y_pos,
my_width, my_height
NULL, NULL, hInstance, NULL );
Here follows an example of a function definition:
bool do_something_today( with, these, parameters ) {
get_up();
go_to( work, car );
work();
go_to( home, car );
sleep();
return true;
}
Make sure your functions don't get too long. Or to
quote Linus:
The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case-statement, where you have to do lots of small things for a lot of different cases, it's ok to have a longer function. However, if you have a complex function, and you suspect that a less-than-gifted first-year high-school student might not even understand what the function is all about, you should adhere to the maximum limits all the more closely. Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it's performance-critical, and it will probably do a better job of it that you would have done).
For the naming of classes I use the same UpperCamelCase as for types. Don't bother putting a 'C' as a prefix for every class, it's just a waste of bytes and time.
As for everything, give classes clear and obvious names. So if a class is a child of class "Window", name it "MainWindow".
When creating a new class, remember that everyting starts from data structures.
Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.Fred Brooks
"Is a" relationship should be modelled by inheritance, "has a" should be modelled by containment. Make sure you don't overuse inheritence, it is a great technique, but only when applied properly.
You should definitely make a distinction between members and normal variables. If you don't do this, you'll regret it later on. Some possibilities to name them are m_Member or fMember. I prefer to use my_member for non static members and our_member for statics. This way you get nice sentenses in you method bodies like
if( my_help_button.is_pressed() ) {
our_screen_manager.go_to( HELP_SCREEN );
}
For the rest everything that applies to variable
naming also applies to members. There is one problem
that I was unable to fix as of yet, and that is with boolean
members. Remember that boolean values must always have
"is" or "has" in them. When combining this with "my_"
you get crazy stuff like "my_is_old" and
"my_has_childeren". I haven't found the perfect
solution for this yet, so if you have any suggestions,
please mail me!
You shouldn't declare members of a class as public. Sometimes it seems quicker to implement, and therefore better, but oh boy are you wrong (as I was many times before). You should pass through public methods to get to the members of a class.
Everything that applies to functions also applies to methods, so always include a verb in the name. Make sure you don't include the name of the class in your method names.
Align simular lines to give your code a better overview, like:
int object_verts[6][3] = {
{-100, 0, 100}, {100, 0, 100}, { 100, 0, -100},
{-100, 11, 100}, (100, 0, -100}, {-100, 0, -100}
};
RECT rect;
rect.left = x;
rect.top = y;
rect.right = rect.left + width;
rect.bottom = rect.right + height;
Never put multiple statements on the same line unless you have a good reason for it. One or those reason could be that simular lines can be put right after each other for clarity, like:
if( x & 0xff00 ) { exp -= 16; x >>= 16; }
if( x & 0x00f0 ) { exp -= 4; x >>= 4; }
if( x & 0x000c ) { exp -= 2; x >>= 2; }
Related variables of the same type can be declared in a common statement. This makes the code more compact and provides a nicer overview. But never declare unrelated variables in the same statement!
int x, y;
int length;
When I start a project I don't do that much upfront design. I just have a global structure in my mind and start coding. Code evolves, whether you like it or not, so give it the chance to evolve.
Evolving code means reworking bad code, and after some programming your code will turn bad. I use following rules to keep a good structure in the code.
Some projects may become big, verry big. A way to cope with this increasing complexity is splitting your project up into different layers. In practice, layers are implemented as namespaces. Lower layers are used by the higher layers. So every layer provides functionality to the above, and the topmost provides functionality to the user.
Files should be named after the class they contain. Don't put more than one class in a file, so you know where to look when you search a specific class. The directory structure should represent the namespaces.
C or C++ header files show the interface of the implementation. This is crucial knowledge when designing the layout of a .h file. In a class, first define the "public" interface that can be used by other classes, then define all "protected" methods and members. This way the most important information for people using the class is shown first. I don't use private methods or members so all members are grouped at the bottom of the class declaration. This way you have a quick overview of the contents of the class at the bottom. Group the methods together by their meaning.
/*
* license header
*/
#ifndef NAMESPACE_FILENAME_H
#define NAMESPACE_FILENAME_H
#include <std>
#include "others.h"
namespace dewitters {
class SomeClass : public Parent {
public:
Constructor();
~Destructor();
void public_methods();
protected:
void protected_methods();
int my_fist_member;
double my_second_member;
const static int MAX_WIDTH;
};
extern SomeClass the_some_class;
}
#endif
.java or .cs files don't provide an interface to the class, they just contain the implementation. Since data structures are more important than algorithms, define your members before your methods. This way when you browse through the code, you have a quick impression of the class through its data members. Simular methods should be grouped together.
Here follows a sketchy overview of a .java or .cs file:
/*
* license header
*/
package com.dewitters.example;
import standard.modules.*;
import custom.modules.*;
class SomeClass extends Parent {
public final int MAX_WIDTH = 100;
protected int my_first_member;
protected double my_second_member;
Constructor() {
}
Methods() {
}
}
Some people like to put little jokes in their code, while others hate this kind of funny stuff. In my opinion you can use them as long as the joke doesn't interfere with the readability of the code or execution of the program.
Here I will present you with some live action code. I stole some code from others and rewrote it to my style. Decide for yourself if my style is better or not. In my opinion you can read faster through my code since it is shorter, and all identifiers are carefully named.
If you think you have seen code that can beat the crap out of my style, just just mail it to and I will write it in the most extraordinary 'deWiTTERS' style and post it here.
/*
*skyblue()
*
*Determine if the sky is blue.
*/
int/* TRUE or FALSE */
skyblue()
{
extern int hour;
if (hour < MORNING || hour > EVENING)
return(FALSE);/* black */
else
return(TRUE);/* blue */
}
/*
*tail(nodep)
*
*Find the last element in the linked list
*pointed to by nodep and return a pointer to it.
*/
NODE */* pointer to tail of list */
tail(nodep)
NODE *nodep;/* pointer to head of list */
{
register NODE *np;/* current pointer advances to NULL */
register NODE *lp;/* last pointer follows np */
np = lp = nodep;
while ((np = np->next) != NULL)
lp = np;
return(lp);
}
bool sky_is_blue() {
return the_current_hour >= MORNING && the_current_hour <= EVENING;
}
Node* get_tail( Node* head ) {
Node* tail;
tail = NULL;
Node* it;
for( it = head; it != NULL; it = it->next ) {
tail = it;
}
return tail;
}
/*
* Summary: Determine order of attacks, and process each battle
* Parameters: Creature object representing attacker
* | Creature object representing defender
* Return: Boolean indicating successful fight
* Author: Ryan Campbell
*/
function beginBattle(attacker, defender) {
var isAlive; // Boolean inidicating life or death after attack
var teamCount; // Loop counter
// Check for pre-emptive strike
if(defender.agility > attacker.agility) {
isAlive = defender.attack(attacker);
}
// Continue original attack if still alive
if(isAlive) {
isAlive = attacker.attack(defender);
}
// See if any of the defenders teammates wish to counter attack
for(teamCount = 0; teamCount < defender.team.length; i++) {
var teammate = defender.team[teamCount];
if(teammate.counterAttack = 1) {
isAlive = teammate.attack(attacker);
}
}
// TODO: Process the logic that handles attacker or defender deaths
return true;
} // End beginBattle
function handle_battle( attacker, defender ) {
if( defender.agility > attacker.agility ) {
defender.attack( attacker );
}
if( attacker.is_alive() ) {
attacker.attack( defender );
}
var i;
for( i = 0; i < defender.get_team().length; i++ ) {
var teammate = defender.get_team()[ i ];
if( teammate.has_counterattack() ) {
teammate.attack( attacker );
}
}
// TODO: Process the logic that handles attacker or defender deaths
}
Copyright (c) 2005 Koen Witters
Last modified: Tue Oct 25 21:20:13 CEST 2005