My app is a Perl Tk app and has grown rather large. Since I sometimes will have to rerun little bits of debugging steps in the future, I leave my warn statements in the code, just comment them out when I don't need them. The trick is to start all such debug-flavor warn messages in column 0. This makes them easy to distinguish from real warn statements which are indented further into the code. After using the warning for the first time, comment away the warning with an initial # sign.

When I want to reuse a given warning, I uncomment the line, and when I'm ready to turn them off again, finding them is easy in vim because I only have to look for warn at the beginning of lines, i.e. I search for ^warn. When I find an uncommented warn, I do a I# to comment it away again, do a n to find the next uncommented warning and do a dot command to repeat the "comment away" command.

This way you can just say $debugging = 1; instead of changing many lines of code. vim is a great tool, but it isn't a debugger. For debugging, you need emacs. :-)

Update: You could even have $::debugging set by command-line switches, or an %ENV variable or a CGI parameter. Then you would not need to change any of the code to get some debugging info. This is great if something prevents you from touching the code, for example if it is running on a production web server.

Generally a good approach, except that my programs are large and that could turn on hundreds of warnings. For me, I generally just need to turn on a few warnings at any given time and it's no big deal to hop around to those four or five that I've unmasked to comment them back up.

My code is usually littered with stuff like
print "Foo: ".Dumper(\$foo) if $debug>7;

Often I write those in not knowing if I'll ever want
that level of verbosity; usually I never have to crank
$debug higher than 2 or 3. (1 just prints progress
info usually, depending on what the app is; 2 gives
more detail, and so on. 0 only prints actual errors,
and undef suppresses non-fatal errors. Anything past
5 is dumping lots of big data structures.) Occasionally
I do end up cranking it way up, though, and adding
in extra print statements like the above, that I
didn't originally anticipate needing.

When I write CGI scripts, I like to have a &printError(); routine. Then all my debug statments call &printError("Message", $debug_level);. Based either on a config file, or and environment variable, &printError(); can decide whether or not $debug_level is high enough to send the message out to STDERR.

Also along these lines, I like to use lines that start with if 0 and if 1 as additional debugging tools. I particularly use this approach with a little subroutine that invokes Dumper (I could probably do this directly, but anyway). Again, when I want the program to dump the object, it's easy to flip the '0' to '1', and when I'm done with the need to see such output, I can easily find all patterns of ^if 1 and flip the '1' back to '0'.