In a few places in our code we use #if DEBUG blocks to simplify development. Things like:

   serverIP = localhost;
   serverIP = GetSetting()


private bool isLicensed()

   return true;

return CheckSetting()

There are also a few places where we make cosmetic changes like this:

   background = humorousImage.jpg
   background = standardColor

Is it dangerous to depend on #if debug to make development easier? If it is, what is a valid use of #if debug?

+9  A: 

Ideally, I think you would move these settings to configuration files and keep the #IF Debug directives for testing, logging, and additional "debugging" tasks. Also, keep in mind that customer facing code that you ever needed to provide a "debug" build for would now behave entirely different. My two cents.

Of course, a "debug" build could be as simple as emitting debugger output in release version. I would think the main reason not to do this is that the release-build could contain bugs that do not exist in the debug-build.
BlueRaja - Danny Pflughoeft
+6  A: 

I can't say this is something I'm keen on doing, personally - I work in an environment where our main application (deployed to 400+ users) has 60+ modules - and with 5 developers working on the projects and releasing modules, you just know sooner or later someone will accidentally release a debug module. :)

Will A
Agreed! It doesn't matter how careful you are - eventually it might see the light of day so it's not worth risking it.
Sounds like you need an automated build, so you're not releasing files built on an individual dev's workstation.
Joe White
Very true - it's been on the cards for a while, Joe!
Will A
+9  A: 

The problem with doing this is that it makes you much less likely to find bugs in the #else.

In general, your debug builds should be as similar as possible to your release builds.

+1  A: 

The first valid use I've had for a conditional #if block:

We have a new licensing / activation system. We need it disabled for local debugging, but don't want to use a config setting to disable it - then the user could get around the system by modifying the config file!

So, we use a conditional compilation block:

// activation code here

Hope that helps paint the picture a bit more..!

Kieren Johnstone
+3  A: 

You should try to keep the live environment and the development environment as similar as possible, so avoid having two versions of the code.

One valid use of the #if DEBUG construct is to put extra checks in the code, that is not needed in the final product:

  if (somehting that normally can't happen) throw new SomeException();
Though that might be done more simply with Debug.Assert().
Joe White
@Joe: Yes, for this simple example, but you might want to check something that requires more complex code.
+6  A: 

It is a really bad idea. If you're trying to catch a production bug your debug clauses will certainly trip you up at some stage or another. You want to be as close as possible to code that runs in production. In your example you'll never be able to find a bug in CheckSetting()

By the looks of things your code is too tightly coupled. What you want to be doing is to make modules/classes less dependent on each-other and practice Test Driven Development. Also have a look at Inversion of Control (aka Dependency Injection).

Working Effectively with Legacy Code has some useful insights on how to introduce TDD. It also has some really good pointers on how to do TDD in various scenarios where it might be hard to test things.


My current style is to have a file called aadebug.h which contains a bunch of conditional defines, each of which may be preceded by // to deactivate it. The file starts:

//#define DX_DEBUG
#ifdef DX_DEBUG

If DEBUG is enabled, the main-screen display code will show "NOT FOR PRODUCTION USE". All debug-only options may be disabled by turning off DX_DEBUG, but most options are generally controlled using individual flags. If I decide an option has outlived its usefulness, I'll remove its #ifdef's from the source and then remove the commented-out #define from aadebug.h, but otherwise I use the commented-out #define's to keep track of which #ifdef flags still exist.