davidj has asked for the wisdom of the Perl Monks concerning the following question:

Ya gotta love debugging, right? :)

Like many of you, I use several debugging techniques. If the program is small and not too complicated, then simple print statements usually suffice.

When code gets more complex, I lean toward the perl debugger since print statements quickly generate code bloat and become increasingly less useful as code becomes more complex. While the debugger is nice, I find that it can get a bit painful when debugging larger programs (especially ones that use complex data structures). I hate to have to "s" or "c" through the debugger to get to the point where my code fails. This is especially true if it is inside a loop that executes many, many times. Even setting watchpoints is sometimes less than useful.

Lately, I have been doing something to simulate C/C++ assert() functionality. (The thing I like about C/C++ assert() is that it only does something if the test condition you supply is true). My assert() simulation looks something like this:

use strict; use constant DEBUG => 1; # many lines of code here &assert($val, $var1, $var2) if DEBUG; # many lines of code here sub assert() { my $test = shift; my (@vars) = @_; # test $test for condition # if test condition is true # do something with @vars (usually dump them) print "would you like to abort: "; my $ans = <STDIN>; exit if $ans =~ m/y/i; }
While this seems to work for me, it also seems a bit clunky (and not very robust).

I'm curious about:
   1) ways I can enhance what I am already doing.
   2) what methods others of you are using.
   3) if there are any modules that I could use (or maybe write my own using what I have as a basis and enhancing it).

as always, your input is valued and appreciated

--david

Replies are listed 'Best First'.
Re: C/C++ type assert() in Perl?
by herveus (Prior) on Jun 09, 2004 at 17:01 UTC
      To me assert seems a silly way to debug. I mean you really have two options:
      # Assert that the sun must rise in the next 24 hours. assert(($next_sunrise_time - time) < 24*60*60) if DEBUG; # Assert that your customer's primary credit card is active affirm { my @cards = @{$customer->credit_cards}; $cards[0]->is_active; };
      Option option one means you must almost know the variable at the time you write the code. Option two means you write a block of code to verify the contents. In my mind both types of var verification inline lead to a problem -- if you made a mistake dealing with the variable earlier in your code what makes you think your asserts will be golden? Adding code like this to a longer app just seems to possibly add more areas for failure. I would tend to use simple log prints on short apps, or on longer (more complex and reused) apps use a testing framework and the debugger to debug.


      -Waswas
        I learned that asserts are supposed to be used to
        guarantee that the programmer did not make a mistake in
        his coding, and pass in bad values to a subroutine.

        In the case of the credit card, it would be pointless to assert() that the card is active.
        It would be prudent, however, to assert() that the program passed in a valid card to
        the subroutine that checks for active cards. Whether or not the card is active is not
        a programming error. Not passing a valid card in certainly is.
Re: C/C++ type assert() in Perl?
by Arunbear (Prior) on Jun 09, 2004 at 17:06 UTC
Re: C/C++ type assert() in Perl?
by Ovid (Cardinal) on Jun 09, 2004 at 20:07 UTC

    If you're going to roll your own, may I suggest that you have assert() determine whether or not it's going to do anything? Also, make it an environment variable so you can test it on the command line rather than have to alter the code. You could also do the test in the sub call, but that's going to slow things down every time. Using your example:

    use strict; # many lines of code here assert($val < $var1, $message); # many lines of code here sub assert() { return unless $ENV{DEBUG}; my ($result, $message) = @_; die $message unless $result; }

    Another method would be to check out Test::AtRuntime.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: C/C++ type assert() in Perl? (see perl 5.9.1)
by grinder (Bishop) on Jun 09, 2004 at 20:28 UTC

    At the French Perl Workshop held a few days ago, Rafael gave a talk on is expected to be delivered with perl 5.10. One item of interest was that of assertions using subroutine attributes. Check it out.

    - another intruder with the mooring of the heat of the Perl

Re: C/C++ type assert() in Perl?
by blueAdept (Beadle) on Jun 09, 2004 at 19:17 UTC
    Data::Dumper would seem a classic choice for your purpose of enhancing what you have.

    While I'm already posting I'll give my $.02 of style for short programs. I like to pre-declar a subroutine named "dprint"(debug print), and it varies from program to program that I write - but usually its something like this:
    our $DEBUG = 1; sub dprint; <.. Insert record into database .. > dprint "Added record $x to database"; <...> sub dprint { my $lt = scalar(localtime()); print "$lt - $_[0]\n" if ($DEBUG); }
Re: C/C++ type assert() in Perl?
by ChrisS (Monk) on Jun 09, 2004 at 21:28 UTC
    You might want to consider Aspect Oriented Programming as a technique for adding cross-cutting behavior, like debug output and logging. (AOP can do a lot more than that, but those are two common uses.)

    I am not an expert at AOP, but it might be worth a look.

    The Aspect module and associated documents could get you started.