Is it a bad idea to put development shortcuts in #if DEBUG blocks?
In a few places in our code we use #if DEBUG blocks to simplify development. 开发者_如何学C Things like:
#if DEBUG
serverIP = localhost;
#else
serverIP = GetSetting()
#endif
or
private bool isLicensed()
#if DEBUG
return true;
#endif
return CheckSetting()
There are also a few places where we make cosmetic changes like this:
#if DEBUG
background = humorousImage.jpg
#else
background = standardColor
#endif
Is it dangerous to depend on #if debug to make development easier? If it is, what is a valid use of #if debug?
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.
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.
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.
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. :)
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 DEBUG
if (somehting that normally can't happen) throw new SomeException();
#endif
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:
#if !DISABLE_ACTIVATION
// activation code here
#endif
Hope that helps paint the picture a bit more..!
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 #define DX_SKIP_LOGIN // #define DX_ALLOW_BULK_USER_CREATE #define DX_CREATE_EXCESS_LOGS // #define DX_RANDOM_PROBE_FAILURES #define SHORT_KEY_TIMEOUT // #define DX_OMIT_NET_VIEWER ... #endif
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.
精彩评论