Limegarden.net Personal site of Wouter Lindenhof

21Mar/101

“Ordered Programming” Technique

When it comes to programming there many, many techniques. One of the techniques I tried is ordered programming. The idea behind it is that quality is assured and nothing can be forgotten. While I was rewriting Brick I decided to use this technique. What it basically does is that you write a “TODO” in the code, for example: “Load configuration file”. And when you run the application in debug mode, it will break when it arrives at that point.

As you can see this has one huge disadvantage and that is that in order to run the entire program all the “TODO” have to be resolved. There is also one huge advantage which is that after you have done something, you will change “TODO” in to “DONE”. The next time you go trough your application, you will notice that the code has now been documented. This is a huge advantage when you write large pieces of code, which you will rarely though in the near future.

However the disadvantage, having to program in the order that the program runs might be too big in some cases. For example some features will be added later as they are not needed now. For example you have written a OBJ loader that handles triangles, but not quads, in this case you might not want to write the quad loading code just yet as you have to focus on the rendering part. For that reason I have decided to add levels, the lower the level the higher the priority. You can think of it in terms as first todo, second todo, etc. If you reach a stage in your development, where you have done all first todo’s, you just increase the number and see where it breaks then.

Here is an example of how it looks when you are writing todo’s.

[cc_cpp]
#include "OrderProgramming.hpp"
int main(int argc, const char** argv)
{
ORDER_PROG_TODO("Setup Memory Checkpoint", 0);
ORDER_PROG_TODO("Initialize graphics engine", 0);
ORDER_PROG_TODO("Run the game", 0);
ORDER_PROG_TODO("Shutdown the graphics engine", 0);
ORDER_PROG_TODO("Check if there are memory leaks", 0);
}
[/cc_cpp]

And here how it looks at a later stage

[cc_cpp]
#include
#include "OrderProgramming.hpp"
class IGraphics;
IGraphics* InitGraphicsEngine();
void GameFunction(IGraphics* graphics);
int main(int argc, const char** argv)
{
_CrtMemState memstate;
_CrtMemCheckpoint(&memstate);
ORDER_PROG_DONE("Setup Memory Checkpoint", 0);

IGraphics* myGraphics = InitGraphicsEngine();
ORDER_PROG_DONE("Initialize graphics engine", 0);

GameFunction(myGraphics);
ORDER_PROG_DONE("Run the game", 0);

if(myGraphics)
delete myGraphics;
ORDER_PROG_DONE("Shutdown the graphics engine", 0);

_CrtMemDumpAllObjectsSince(&memstate);
ORDER_PROG_DONE("Check if there are memory leaks", 0);
}
[/cc_cpp]

And here is the header you will need to include:

[cc_cpp]
// OrderProgramming.hpp
// Generic functions can be defined before inclusion
// - ORDER_PROG_DEBUGBREAK: Breaks the process if possible
// - ORDER_PROG_ASSERT: Tries to assert a function
// - ORDER_PROG_OUTPUT: Debug output function
#ifndef __ORDER_PROGRAMMING_HPP__
#define __ORDER_PROGRAMMING_HPP__

#define ORDER_PROG_STRINGIFY(x) #x
#define ORDER_PROG_TOSTRING(x) ORDER_PROG_STRINGIFY(x)
#define ORDER_PROG_FILE __FILE__
#define ORDER_PROG_LINE ORDER_PROG_TOSTRING(__LINE__)
#define ORDER_PROG_HERE ORDER_PROG_FILE"("ORDER_PROG_LINE") : "

#ifndef ORDER_PROG_DUMMY
# define ORDER_PROG_DUMMY() {(void)0;}
#endif
// Lower than this level will cause the order to be taken in account
#ifndef ORDER_PROG_LEVEL
# define ORDER_PROG_LEVEL 1
#endif

#ifndef ORDER_PROG_DEBUGBREAK
# if defined(_WIN32)
# include
# define ORDER_PROG_DEBUGBREAK __debugbreak();
// # elif (???)
# else
# define ORDER_PROG_DEBUGBREAK {__asm{int 3};}
# endif
#endif

// Platform independent (most of the time)
#ifndef ORDER_PROG_ASSERT
# include
# define ORDER_PROG_ASSERT(expression) assert(expression);
#endif

// Platform dependent
#ifndef ORDER_PROG_OUTPUT
# if defined(_WIN32)
# include
# define ORDER_PROG_OUTPUT(output) OutputDebugStringA((output));
//# elif (???)
//# define ORDER_PROG_OUTPUT(output) ::std::clog << (output);
# else
# define ORDER_PROG_OUTPUT(output) ORDER_PROG_DUMMY()
# endif
#endif

#ifdef ORDER_PROG_NOBLOCK
# define ORDER_PROG_BLOCK(reason) ORDER_PROG_DUMMY();
#else
# define ORDER_PROG_BLOCK(reason) ORDER_PROG_ASSERT(0 && (reason))
#endif

#define ORDER_PROG_TODO(reason, level) { if((level) < ORDER_PROG_LEVEL){ ORDER_PROG_DEBUGBREAK; ORDER_PROG_BLOCK(reason) } }
#define ORDER_PROG_TODO0(reason) ORDER_PROG_TODO(reason, 0);

#define ORDER_PROG_DONE(reason, level) { if( (level) < ORDER_PROG_LEVEL) { static bool _once=true; if(_once) { ORDER_PROG_OUTPUT(ORDER_PROG_HERE); ORDER_PROG_OUTPUT(reason); ORDER_PROG_OUTPUT("\n"); _once = false; } } }
#define ORDER_PROG_DONE0(reason) ORDER_PROG_DONE(reason, 0)

#endif // __ORDER_PROGRAMMING_HPP__
[/cc_cpp]

Comments (1) Trackbacks (0)
  1. Interesting idea. I think I’ll try that…


Leave a comment

(required)

No trackbacks yet.