Tao of Coding by Koen Witters

Introduction

  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 [1]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.

Why a Coding Style?

  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:
   1. Develop clean and readable code, so when someone else has to dig
      through it, he can pick it up rather quickly. And more important
      when you get back to some old code you have written a year ago, you
      don't start thinking "I can't remember being that wasted...".
   2. When working in team, it's best that everybody uses the same style
      so the code has a uniform look.

  Since I develop most of my code on my own, I don't have to consider the
  second reason. And since I am very stuburn, I am not going to take over
  someone elses style. That's why my style is completely optimized to
  produce clean and readable code.

The Basic Rules

  I tried to capture the most important aspects of coding style in the
  following rules.
   1. All should be as understandable as possible.
   2. All should be as readable as possible, except when it would
      conflict with the previous rule.
   3. All should be as simple as possible, except when it would conflict
      with the previous rules.

  The best way to look at these rules is make everything as simple as
  possible, unless understandability or readability suffer. Or to quote
  Albert Einstein:

    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

Identifiers

  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.

Variables

  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:

  is_, has_
         Use these for all boolean values so there can be no mistake
         about their type. It also fits nicely in if statements.

  the_
         Start all global variables with "the_", which makes it verry
         clear that there is only one.

  _count
         Use _count to represent the number of elements. Don't use plural
         like "bullets" instead of "bullet_count", as plural will
         represent arrays.

  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]".

Const or Final

  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

  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 ];

Program Flow

 if, else if, else

  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

  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

  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

  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

  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 );

 Definition

  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).

Classes

  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

 Inheritence

  "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.

 Members

  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.

 Methods

  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.

Code Structure

  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;

Namespaces, packages

  Namespaces or packages should be written in lower case, without any
  underscores. Use a namespace for every module or layer you write so
  that the different layers become clear in the code.

Design

  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.
   1. When a functions gets too big, divide the problem in some smaller
      helper functions.
   2. If a class contains too many members and methods, split a part of
      the class up in a helper class and include the helper class in your
      main class (don't use inheritence for this!). Make sure your helper
      class doesn't reference or use the main class for anything.
   3. When a module contains too many classes, divide it up into more
      modules where the higer level module make use of the lower level
      module.
   4. When you are done implementing a feature or fixing a bug, read over
      the entire files you have changed to make sure everything is in the
      most perfect state.

  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

  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.

 .h file structure

  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 .cs file structure

  .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() {
       }
   }


Jokes

  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.

deWiTTERS Style vs. others

  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.

 Indian Hill C Style

/*
*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);
}


   Rewritten to deWiTTERS Style:

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;
}


 "Commenting Code" from Ryan Campbell

/*
* 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

   Rewritten to deWiTTERS Style:

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
    __________________________________________________________________

  Archived with explicit permission from Koen Witters by Chris Lott on 1
  Nov 2005.

References

  1. https://maultech.com/chrislott/resources/cstyle/witters_tao_coding.html#vs