Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding messiness with debug stuff in code

When I write something, half the effort tends to go into adding clear and concise debug output, or functionality that can be enabled/disabled when that something needs debugging.

An example of debug functionality is a downloader class where I can turn on a #define which makes it "pretend" to download the file and simply hand me back the one I have already. That way I can test to see what happens when a user downloads a file, without having to wait for the network to physically grab the file every single time. This is great functionality to have, but the code gets messier with the #ifdefs.

I eventually end up with a bunch of #defines like

// #define DEBUG_FOOMODULE_FOO
// #define DEBUG_BARMODULE_THINGAMAJIG
// ...

which are uncommented for the stuff I want to look at. The code itself turns out something like

- (void)something
{
    #ifdef DEBUG_FOOMODULE_FOO
    DebugLog(@"something [x = %@]", x);
    #endif
    // ...
    #ifdef DEBUG_FOOMODULE_MOO
    // etc
}

This works great for writing / maintaining the code, but it does nothing for the appearance of the code.

How do people write effortless on-the-fly long-term debug "stuff" anyway?

Note: I'm not only talking about NSLogging here... I'm also talking about stuff like the pretend-download above.

like image 846
Kalle Avatar asked Jul 20 '11 12:07

Kalle


1 Answers

I read several libraries before writing my own and saw two approaches: macro + C functions (NSLogger) or macro + Singleton (GTMLogger, Cocoa Lumberjack).

I wrote my naive implementation here using macro + singleton. I do this during runtime:

[Logger singleton].logThreshold = kDebug;
trace(@"hi %@",@"world); // won't show
debug(@"hi %@",@"world);

You could do the same for packages instead log levels. If I want it gone, I change the #defines. Here is the code involved:

#define trace(args...) [[Logger singleton] debugWithLevel:kTrace line:__LINE__ funcName:__PRETTY_FUNCTION__ message:args];

if (level>=logThreshold){
  // ...
} 

If you want something more sophisticated look into Lumberjack, it has a register class facility to toggle logging for some classes.

like image 199
Jano Avatar answered Sep 18 '22 05:09

Jano