in reply to Instrumenting code for debugging.

This is somewhat personal style - but these are the levels I tend to migrate through.

First of all I write all of my code test first. I moved over to this style a couple of years ago. I find it gives me a far better knowledge of my code state, so I spend far less time sprinkling debug statements around.

The stuff that you mark with XXX I would mark by a failing test or a TODO test (the latter being an exceptionally neat feature of Perl's testing framework not found in the systems I have used in other languages).

If I've got a quick question about what $foo is at some point in my code I'll just add:

warn "foo is $foo";

and delete it as soon as I have an answer to my question.

I only do this when I'm sorting unit tests. Code with debug warnings in never hits the CVS tree.

If I need to leave the debug statements in for a bit I stick a constant into the module.

use constant DEBUG => 1; ... warn "foo is $foo" if DEBUG; warn "bar is $bar" if DEBUG > 2; ...

Again, I only use this when I'm sorting unit tests. Code with warnings can hit the CVS tree, but only when DEBUG => 0.

If I have bugs during integration and need to switch debugging info on and off in several modules I will use some variant of Poor man's logging.

Anything more complex means that I'm in the realm of logging, rather than debugging so I'll use a proper logging module like Log::Log4Perl.

Replies are listed 'Best First'.
(Re:)+ Instrumenting code for debugging.
by rir (Vicar) on Mar 13, 2003 at 17:52 UTC
    I write all of my code test first. ... I find it gives me a far better knowledge of my code state, so I spend far less time sprinkling debug statements around.

    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.

    Part of this is a prejudice toward testing small chunks of code, then writing tests for those pieces as a unit.

    I will consider using TODO tests, thanks adrianh. My XXX's mark the location of the bad code, and it is known to be bad. (That statement demonstrates that I have not internalized the XP attitude to testing.)

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

    Thanks Poor man's logging is one nice answer to my command line query.

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

      • There is something seriously wrong with my code
      • I should be using a proper logging module.
      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!

        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.

testing framework?
by agh (Novice) on Mar 14, 2003 at 16:35 UTC
    Could you give a pointer to the testing framework you mentioned?