in reply to Re: Re^3: Instrumenting code for debugging.
in thread Instrumenting code for debugging.

Regarding the need for extra flexibility in your debug statements indicating a serious wrongness in your code. Well, yes, um, ah, sure. I would hope that your debugging statements would help with serious problems in your code. That is the point isn't it.

Yes :-)

What I was trying to say was that the very fact that I need N mutually independent streams of debugging information to track down a bug is a indicator of a larger design problem. It means I must have a whole bunch of tightly coupled stuff that needs to be uncoupled.

Flexibility, here, is a good thing. The convenience of getting just the pertinent info at the cost of being limited to, likely, 32 debug levels is a good trade. Not that I expect anyone to start refactoring. Just mentioning a refinement.

It's useful when you need it. However, I'd probably use something like Log::Log4perl rather than something hand rolled.

The distinction you make between debugging output and logging is fuzzy to me.

It's fuzzy to me too :-) At least the border between the two is, the extremes are not.

I add debugging output when I'm tracking a particular problem. It's a precision tool aimed at illuminating a specific instance of incorrect behaviour. It may well be computationally expensive. It's not generally useful information so it's pointless to keep it in after the code has been fixed.

Like comments, code that does not run gets out of sync with the code that does run. I've spent too much time with other peoples code that has things like:

warn "panic!\n" if $x->{limit} < 0 if $DEBUG;

When there is no other mention of limit in the codebase :-)

Logging, on the other hand, illuminates the normal operation of the code. It's general, structured, and usually computationally cheap.

That's why I said I "these are the levels I tend to migrate through" - I tend to go from unstructured short-term debug warnings, to a structured logging system as and when the project warrants.

Here we are skirting one of my questions: What are the trade-offs between having a module contain its debugging code versus depending upon another module?

My attitude is if you need to have the same debugging subroutines in more than one place you should stick it in a module. Repeated code is bad.

If you need the flexibility, use an existing system like Log::Log4Perl or Log::Dispatch.

Another issue you may have to consider the cost of the debugging code. With most setups you have the expense of a subroutine call and a comparison even with debugging disabled.

Using a simple system with constant subroutines means Perl can optimise that all out. For example, we could implement your original example like this:

#! /usr/bin/perl # debugging levels use constant NONE => 0; use constant BUG => 2**0; use constant TRACE => 2**1; use constant ALL => 2**2 - 1; # current level use constant DEBUG => NONE; sub routine { warn "debug message" if DEBUG && "something"; warn "trace message" if DEBUG & TRACE; }

and perl will happily optimise out the warn lines when they cannot be called. It's still readable so this may be all you need.

I have found the lack of debugging statements in my code to be unsettling at times. To know that I instrumented the code and promptly deleted it three years ago only distracts from the task of understanding the code again.

Another reason I don't leave debugging statements in is that I always write a failing test when I find a bug. In fact that's the first thing I do. That way I know when the bug has gone (the test passes) and I know it won't be back (because the test will fail if it returns). During the process of locating the bug I may well add other failing tests as I discover other ambigous areas of code. I do not remove tests after I have written them (at least not without a great deal of thought).

This way you keep all of your debugging knowledge explicitly in the tests, while keeping your codebase clean.

Tracing, pre-, post-conditions, some other assertions are all debugging statements to keep.

To me these are not debugging statements - they are documentation. You don't delete documentation ;-)

Others may just be noise. I'm going to apply my rule two paragraph 4 and experiment with keeping them all. It should not be too cluttering because it will be my clutter and it had some, my, motive to exist. This will be a long experiment.

Luck. Let us know how it goes.