Arnaud "Arhuman" Assad


Devel::StealthDebug - Simple non-intrusive debug module


# in user's code:

use Devel::StealthDebug;

... #!assert(<cond>)!

 will die at this line if <cond> is not verified...

... #!watch(<var_name>)!

 will carp each access to <var_name> 
 (Idea from Srinivasan's monitor module)

... #!emit(<double_quoted_string_to_be_printed>)!

 will 'emit' the string Depending on emit_type
 it will print, carp, croak or add to a file

 carp is the default value for emit_type

... #!dump(<ref to a variable to be dumped>,<another ref>,...)!

 will emit the variable's structure

... #!when(<var_name>,<op>,<value>)!

 will emit when <var_name> will pass the condition described by 
 <op><value>. Currently, only works for 'watched' scalar... 

... #!emit_type(carp|croak|print)!

 Define the emit's behaviour 

 Can also be set on the use line :
 use Devel::StealthDebug emit_type => 'croak';

 Note that if you set it this way you gain an additional feature, 
 you can now emit to a file :
 use Devel::StealthDebug emit_type => '/path/to/file';
 'carp' being the default value

 You can also pass other optionq on the use line :

 use Devel::StealthDebug  ENABLE=>'/path/to/file';
 use Devel::StealthDebug  ENABLE=>$ENV{WHATEVER};
 use Devel::StealthDebug  DUMPER=>1;

 The third form will make the 'dump' function use Data::Dumper.

 The second form enable debugging only if the var passed as value is 'true'
 (i.e. different from undef,'',zero, or empty list)
 The first form will enable the debug instructions if
 '/path/to/file' don't exist or exist AND contain a line (regex) which match
 the current file name.

 This behaviour may sound odd, but as there's no way to know it you pass a value
 or a filename, a first test is made to check if the file exists, if it isn't 
 the case then a value is assumed (so '/path/to/missing/file' is treated as a
 value which is 'true' and so debugging is enabled).
 If the file exists, debugging is disabled unless this file contains a line 
 whith a regex which matchs the current file name.


This module will allow you to debug your code in a non-intrusive way.


The Story

This module started as a joke called "". Following a discussion with a JAVA zealot (hi Gloom) I coded a short module using Filter::Simple to show that strong type checking and other missing features could be added easily to Perl thanks to filters.

The code posted on produced insightful comments (as always on perlmonks ! Go there it's a GREAT place for any Perl lover) One of them was emphazing the fact that any feature making the debugging easier is a good thing. I then decided to play with Filter::simple to make a useful module. I quickly coded a dirty module to do the job, which stood unused on my hardisk for months. I entually decided that It could be a good thing to release my first module, I did some clean-up, wrote some documentation and : voila !

Why another debug module ?

A simple search on CPAN will lead you to several other useful modules making debugging easier. (for example Carp::Assert) Why did I decide to reinvent the wheel ? Especially when some of the already existing wheel are well crafted. Simply beccause I wanted to explore a new kind of interface.

I wanted a simple and non-intrusive way to make the first stages of coding easier and safer. (By non-intrusive I mean without modyfing the code)

Ideally I wanted to switch-on (via 'use Debug;') a battery of checks without modyfying my code, and then use it in production with only the use line commented out.

I could have used the usual embeded tests triggered by a variable (usually $DEBUG) but I didn't want to pollute the code logic with the debugging statements and I also wanted to play with the wonderful Filter::Simple module.

Furthermore I've tried to group (and when possible enhance) in this modules several features dissiminated (or simply missing) in several modules.


 use Devel::StealthDebug;

 my $foo = 0;
 ... Several processing on $foo
 my $bar = 1 / $foo;    #!assert($foo != 0)!
 my %myhash;                    #!watch(%myhash)!

 sub func1 {                    #!emit(Entering func1)!


Of course, many ;-)

The code could probably be more robust.

For example, I'd strongly suggest to use a SIMPLE instruction on the line where the watch() fonction is :

 my ($foo,%bar);!watch(%bar)!
 will break...

 my $foo;
 my %bar;!watch(%bar)!


Carp::Assert, Filter::Simple


Arnaud (Arhuman) ASSAD <>


Copyright (c) 2001,2002 Arnaud ASSAD. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.