in reply to (Re:)+ Instrumenting code for debugging.
in thread Instrumenting code for debugging.

I find this also. Though I don't have it down to a habit yet. I may write test or code first. I also find testing to eliminate much debugging effort. I usually have an editor on the test file and the code file, write a little, test a little, and vice versa. If I know where I'm going I'm apt to write the test first. When I'm in cut and fit mode, writing tests first seems inefficient.

I went through that stage too, but I now test first for everything. It really made a difference to my code quality. Give it a try for a couple of weeks. You'll like it (why do I feel like a pusher :-)

When writing new code I always have three windows open. One for my test script. One for my module. One for my test output.

I've a little script that runs my tests every time I change a file, so I just spend my development time switching between the test window and the code window. Write test. Hit save. Watch test fail. Write code. Hit save. Watch test pass. Warm fuzzies. Repeat until done. Fun.

It is more flexible to use bitfields instead of additive levels.

True. However I find if I need that level of flexibility for debug statements it's a sign that:

More and more, I lean towards leaving in all the debugging code. If I wanted to check warn "foo is $foo"; why wouldn't I want to leave that pointer for the next reader. There are times that the code is changed and a debug statement becomes superfluous. But in general it is like marking a trail for the next person.

I personally don't find that's true. If the statements are there for debugging purposes (as opposed to logging) I find that they just clutter up the code. If the next person needs the debug statements to understand the code I would start thinking about refactoring the code to make it clearer.

Something else I do more now is use things like Hook::LexWrap to add instrumentation so I don't have to alter the original code at all!

  • Comment on Re^3: Instrumenting code for debugging.

Replies are listed 'Best First'.
Re: Re^3: Instrumenting code for debugging.
by rir (Vicar) on Mar 14, 2003 at 21:54 UTC
    Don't feel like a pusher. I will try to alter my habits. I am less affirmative than usual in this statement because I am not getting to code much lately. I find short periods of coding are not as condusive to changing work patterns.

    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. 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.

    The distinction you make between debugging output and logging is fuzzy to me. 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?

    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.

    Tracing, pre-, post-conditions, some other assertions are all debugging statements to keep. 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.

    Thanks for the Hook::LexWrap reference.

      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.