When your code base grows you will end with dozens of places to change your code, all of them error prone. More things you need to keep control means more potential problems.
There are 2 alternatives to this. For languages that have macros (C#, C, C++) use the #ifdef construct, as others suggested here. For languages that don't have them (Java, Perl) use a less error prone alternative:
static boolean Test = false; // Only one place to change code
...
if(Test) doTest();
The difference in this last technique is that since you have just one place to change code there is less chance for errors and the change is easier to automate.
If you DO want to do this either:
a) delete the code. It'll be in version control anyway right? You do do version control right?
b) put it under a NAMED feature flag. Test is not a suitable name. Put it in a separate file which is conditionally compiled into the build with #ifdef SHINY_FEATURE shiny_feature(); #endif
From "97 Things Every Programmer Should Know" http://programmer.97things.oreilly.com/wiki/index.php/Commen...
> Commented-out code is not executable code, so it has no useful effect for either reader or runtime. It also becomes stale very quickly. Version-related comments and commented-out code try to address questions of versioning and history. These questions have already been answered (far more effectively) by version control tools.
If only digging code up from a previous version was as easy as uncommenting it.
However though, please read https://news.ycombinator.com/item?id=5626456 and summary is:
It is a trick, not a silver bullet. It prevents code from being compiled to the binary, in a portable - yet hacky - way.
#define DEBUG 1
#if DEBUG
test_code()
#else
real_code()
#endif
Much more readable and the DEBUG macro can be defined in a common header, so all of the code can share it.The comment trick isn't useless during development, but I'd see myself using a macro rather than trying to remember just where a slash goes.
More sins have been committed in the cause of "Hey, this will save a few keystrokes" than . . . well, a lot of sins, okay?
I have no trouble doing this in the heat of bring-up or a debugging session, but I'd never check it in, and I hope that none of my cow-orkers ever will, either.
Alternatively if you don't need to check in your comments then your IDE should have a "comment selection" option (CTRL K, C chord in VS)
Before a commit I'll sweep through and delete the intermediate code blocks that I've commented out. If I use pre-compiler flags to comment out the code, it's easy to miss it in the sweep. Because of this I never use the pre-compiler flags for something I don't want to get committed.
Well, it's really only error prone if your editor doesn't have syntax highlighting. Seeing a whole swatch of code turn into the comment color pretty much tells you what's going on.
Still, I think personally I'd rather do an "#if 0". It's still only 1 character to toggle the code on or off...
My only issue using this with things like JS, won't all that code still be loaded into memory giving a misrepresentation of the memory profile of your app?
Yes it will. The alternative for that might be a modular design with very loose coupling and using Inversion of Control. Then, the only change you would need to make would be in the Inversion of Control configuration to load either the test code or the production code. You could place all the debug and trace code inside a single unit and use an empty stub in production. This would avoid sending the test code to the client on the production environment.
I am not an expert in JS, please correct me if this is wrong. I'd do something like this (for checking pre-conditions in method calls):
function Assert(condition, message ){} // this module is loaded/included in production only
function Assert(condition, message) { if(!condition) alert(message);} // this module is loaded/included in tests only
Better would be to collect that code into one or two files at can be included when needed. I would imagine that's really only a concern when downloading code because the compiler should throw dead code ("if false...") away.
if(Test) doTest();
Or something like if (USE_FEATURE_A) runFeatureA();
which allows for more specific, more fine-grain control.Compilers are not uniform in their interpretation of nested comments.
For the love of god, please, they are meant for checking each others code for mistakes and not for miniscule details like this. I have seen it time and time again in various companies where code review is used as some sort of tool to dictate style and preferences to each other. Wasting valuable development time and creating a unhealthy tension between developers.
Code reviews are invaluable in education other developers about your code, how to support it and how to develop on it. But information should also flow the other way and the give the reviewers the opportunity to present the accepted practices to the developer. In the long term, this saves developer time as the code base stays coherent. Code is read many times and needs to be understood by many developers even though it is written only once.
We use various automated techniques to pick up mistakes and use code review to ensure style is consistent.
Everyone in the company should be able to parse any piece of code without individual styles disrupting that.
The only tension occurs around the weighty question of line length - coding standard says 76 chars max, I say that's what the IDE's for.
If you are not compiling on multiple platforms, then complaining about stuff like this because of compiler issues is a nuisance. (You could still object on the basis that it is fugly.)
At best, this gimmick is for hacking out some temp code while debugging, and should not be submitted.
Of course, one should just use an IDE, or even vim, to commenting out code as needed.
/*/ Version one, currently commented
/*/ Version two, currently active /**/
And a single star switches from version two to version one.But I agree this shouldn't be left in production code; it's just a handy trick for switching between two blocks of code†. An #ifdef is also good, but that's C/C++ only.
† Whoever suggested that some editors can comment a block of code missed the point utterly - which is to switch between code blocks easily.
And every language has the IF construct.
And of you are flipping between two implementation so frequently, your actual problem is that you have no idea how your program works.
So can #ifdef TEST / #ifndef TEST , which also has the advantage of not being horrific.
Having said that, there are plenty of cases where you can't use macros (like all languages/compilers/interpreters that don't support them). I don't agree with the author here though. Just comment the damn code out normally until you can clean everything up. Doing it that way encourages leaving that mess intact and forgetting about it.
I mean, if you're talking about basic C, this (_DEBUG) is actually built-in to most systems from the get-go, for exactly this purpose. "Abuse?"
I use this sort of trick all of the time when debugging, but I rarely commit any commented out code as a matter of principle.
Nobody was suggesting using this for "ghetto source control" or that this is an alternative to compiler directives.
Can't we just be polite and say "Cool hack, but obviously don't commit this type of code", instead of getting out the pitchforks?
I would rather make angry comments here than to have to explain why this is a terrible idea in a code review of an intern or a junior colleague.
Second thought: oh boy, Hacker News is going to have a field day with this one.
The reason is that we often need to comment OUT code during development. In C++, the 4 choices are: (1) #ifdef, (2) bool dothis = false; if (dothis) { ... }, (3) /* * /, (4) // ...
Among them, I would say the best and least-confusing way to comment out a block of code is /* * /. #ifdef's are very confusing especially if you have multiple of them; // needs to be applied to every line so only works in small scale; if (dothis) doesn't work across multiple functions, and at a glance it is harder to discern whether this is a "comment-out", or a legit condition.
However, by using /* * / in your comments, you eliminate the possibility of commenting out blocks of code that contains /* * / comments. The problem, of course, is due to how the opening and closing symbols are matched.
#if 0 /* reason /
lines of messy stuff ...
#endif /
reason */That short comment makes it easy for me to find the ends.
/**
testCode(); testCode();
/**/
(...) /**/
productionCode(); productionCode();
/**/
I think this is better because it's much easier to see what you're supposed to do in order to switch the block on or off, and it's only a single character change per block. (though you can't switch from test to production in one character, but meh).However, I tend to see commented code as ugly cruft. To me, comments are for explaining in natural language what you're doing, not for deactivating bits of code. If it's bad get rid of it, if it's good keep it. Why comment code?
The only time I comment out code is to warn developers away from doing something which is obvious but a bad idea, for example:
/*
// This was a neat idea but it makes it break if the user isn't logged in
userPreference = getPrefFromUserSession();
*/You can then put documentation in that test, as that's what the developer will look at first. You also get the bonus that, if someone finds a way to fix the function that causes that, then you can go back to possibly nicer code.
The low cost makes it useful for quick development, sure, but for stability's and sanity's sake, please remove when you start promoting this above your own playground.
#ifdef DEBUG
testCode();
#else
productionCode();
#endif
Or, better yet, if it really is test code then write a test.And tests need to be separated from the code. Hopefully using a test framework.
If your code changes depending on if it is in 'test mode' or not (which is what is proposed), then the test code is not the same as the production code, i.e. the production code is not tested. I'm not just talking about timing issues - extra variable names and objects will be in scope in 'test mode', and might logically change the behavior of the program.
Please read the protip, understand my intention (keyword TRICK) and have a delightful cup of coffee. You've earned it.
Or switch to block selection mode, make a multi-row zero-column selection and type //
I love Eclipse.
Additionally, source control tools make deleting code much more convenient, no?
That said, macros do make sense in this case- you can #define a single flag (e.g. FLAG) as a 0 or 1 and simply #if FLAG ... #endif, but it's certainly more typing to set up.
if (1)
productionStuff();
else
testStuff(); /**/
block one
/*/
block two
/**/
Simply add or remove the second slash to toggle. /*/
test
/*/
test
//*/
Just add or remove the first asterisk.I actually use this a lot for performance comparison. This way it is easy to toggle between the olt d and the new implementation and see how long it takes to run the code 1000 time in javascript.
But I think anyone who check ins something likes this should be slaped.
if you need to have branches in your code, learn how to use your source control environment. even cvs lets you branch your source tree.
The protip is not to use the trick, but to know about it. Read the tip, try to understand the intention - then criticize. Thank you kind sir.l
If you really need to turn code on/off in different environments, you should be using feature flags: http://code.flickr.net/2009/12/02/flipping-out/ and at the very least you should be detecting the environment:
if (ENV == 'dev')
testStuff();
else
productionStuff();
This is much more meaningful to other developers (and to yourself in the future). git co branch
Sorry. I've been burned one too may times from source-control-by-commenting-out.It's a TRICK, and that's all it will ever be.
However, it is the only way I know of that is not language specific for a particular dialect of C (#ifdef) that enables code to _not_ become a part of the compiled binary, or in JS terms - not available from the runtime.
Best regards -OP
Reminds me of another trick for debugging C++ programs. This allows you to dump data structures easily:
#define private public
include <foo.h>For example with NERD Commentor vim plugin, you can toggle block comments with `<leader>c<space>`. Inverting comments is `<leader>ci`.
$ cat test.c
int compiler_supports_single_line_comments = 1 //*
//*/ 2
;
int main(void)
{
return compiler_supports_single_line_comments;
}
$ gcc test.c -o test && ./test ; echo $?
1
$ gcc -std=c89 test.c -o test && ./test ; echo $?
0 #'''
some_code()
'''
some_other_code()
#'''
... with one character toggled, becomes: '''
some_code()
'''
some_other_code()
#'''
If you work with anyone who says "Don't do this," don't do this. --[[
Code block one
--[=[ Explanatory comment here ]]
Code block too
--]=]#define include_them 1 #if (include_them==1) #define hotcode /##/ #else #define hotcode #endif
void func (void) { hotcode printf("if included_them true, compile this line"); }
At least in my IDE anyway.