UPDATE: I've mostly left this Meditation as it was 15 years ago, but since then it's also appeared in Mastering Perl and I'm updating it at briandfoy.github.io.
brian's Guide to Solving Any Perl Problem
Follow this guide and save your sanity
I believe in three things:
- It is not personal
-
Forget about code ownership. You may think yourself an artist, but
even the old Masters produced a lot of crap. Everybody's code is
crap, which means my code is crap and your code is crap. Learn to
love that. When you have a problem, your first thought should be
``Something is wrong with my crappy code''. That means you do not get
to blame perl. It is not personal.
-
Forget about how you do things. If the way you did things worked,
you would not be reading this. That is not a bad thing. It is just
time to evolve. We have all been there.
- Personal responsibility
-
If you have a problem with your script it is just that---your problem.
You should do as much to solve it by yourself as you can. Remember,
everyone else has their own scripts, which means they have their own
problems. Do your homework and give it your best shot before you
bother someone else with your problems. If you honestly try
everything in this guide and still cannot solve the problem, you have
given it your best shot and it is time to bother someone else.
- Change how you do things
-
Fix things so you do not have the same problem again. The problem is
probably how you code, not what you code. Change the way you do
things to make your life easier. Do not make Perl adapt to you
because it will not. Adapt to Perl. It is just a language, not a way
of life.
- Does your script compile with strictures?
-
If you are not already using strictures, turn it on. Perl gurus are
gurus because they use strict which leaves them more time to solve
other problems, learn new things, and upload working modules to CPAN.
-
You can turn on strictures within the code with the strict pragma.
-
use strict;
-
You can turn on strictures from the command line with perl's -M
switch.
-
perl -Mstrict script.pl
-
You may be annoyed at strictures, but after a couple of weeks of
programming with them turned on, you will write better code, spend
less time chasing simple errors, and probably will not need this
guide.
- What is the warning?
-
Perl will warn you about a lot of questionable constructs. Turn on
warnings and help Perl help you.
-
You can use perl's -w switch in the shebang line.
-
#!/usr/bin/perl -w
-
You can turn on warnings from the command line.
-
perl -w script.pl
-
You can use lexical warnings with all sorts of interesting features.
See warnings for the details.
-
use warnings;
-
If you do not understand a warning, you can look up a verbose version
of the warning in perldiag or you can use the diagnostics pragma in
your code.
-
use diagnostics;
- Solve the first problem first!
-
After you get error or warning messages from perl, fix the first
message then see if the perl still issues the other messages. Those
extra messages may be artifacts of the first problem.
- Look at the code before the line number in the error message!
-
Perl gives you warning messages when it gets worried and not before.
By the time perl gets worried the problem has already occurred and the
line number perl is on is actually after the problem. Look at the
couple of expressions before the line number in the warning.
- Is the value what you think it is?
-
Do not guess! Actually examine the value right before you want to use
it in an expression. The best debugger in the universe is print.
-
print STDERR "The value is ]$value]\n";
-
I enclose $value in braces so I can see any leading or trailing
whitespace or newlines.
-
If I have anything other than a scalar, I use Data::Dumper to print
the data structures.
-
require Data::Dumper;
-
print STDERR "The hash is ", Data::Dumper::Dumper( \%hash ), "\n";
If the value is not what you think it is, back up a few steps and try
again! Do this until you find the point at which the value stops
being what you think it should be!
-
You can also use the built-in perl debugger with perl's -d switch. See
perldebug for details.
-
perl -d script.pl
-
You can also use other debuggers or development environments, like a
ptkdb (a graphical debugger based on Tk), Komodo (ActiveState's Perl
IDE based on Mozilla), of Affrus on MacOS X.
- Are you using the function correctly?
-
I have been programming Perl for quite a long time and I still look at
perlfunc almost every day. Some things I just cannot keep
straight, and sometimes I am so sleep-deprived that I take leave of
all of my senses and wonder why sprintf() does not print to the
screen.
-
You can look up a particular function with the perldoc command and its
-f switch.
-
perldoc -f function_name
-
If you are using a module, check the documentation to make sure you
are using it in the right way. You can check the documentation for
the module using perldoc.
-
perldoc Module::Name
- Are you using the right special variable?
-
Again, I constantly refer to perlvar. Well, not really since I
find The Perl Pocket Reference much easier to use.
- Do you have the right version of the module?
-
Some modules change behavior between versions. Do you have the
version of the module that you think you have? You can check
the module version with a simple perl one-liner.
-
perl -MModule::Name -le 'print Module::Name->VERSION';
-
If you read most of your documentation off of the local machine,
like at http://www.perldoc.com or http://search.cpan.org, then
you are more likely to encounter version differences in documentation.
- Have you made a small test case?
-
If you are trying something new, or think a particular piece of
code is acting funny, write the shortest possible program to do
just that piece. This removes most of the other factors from
consideration. If the small test program does what it thinks it
does, the problem probably is not in that code. If the program
does not do what you think it does, then perhaps you have found
your problem.
- Did you check the environment?
-
Some things depend on environment variables. Are you sure that
they are set to the right thing? Is your environment the same
that the program will see when it runs? Remember that programs
intended for CGI programs or cron jobs may see different environments
than those in your interactive shell, especially on different
machines.
-
Perl stores the environment in %ENV. If you need one of those
variables, be ready to supply a default value if it does not
exist, even if only for testing.
-
If you still have trouble, inspect the environment.
-
require Data::Dumper;
print STDERR Data::Dumper::Dumper( \%ENV );
- Have you checked Google?
-
If you have a problem, somebody else has probably had that problem.
See if one of those other people posted something to the usenet group
comp.lang.perl.misc by searching Google Groups
(http://groups.google.com). The difference between people who ask
questions on usenet and those who answer them is the ability to use
Google Groups effectively.
- Have you profiled the application?
-
If you want to track down the slow parts of the program, have you
profiled it? Let Devel::SmallProf do the heavy lifting for you. It
counts the times perl executes a line of code as well as how long it
takes and prints a nice report.
- Which test fails?
-
If you have a test suite, which test fails? You should be able to
track down the error very quickly since each test will only exercise a
little bit of code.
-
If you don't have a test suite, why not make one? If you have a
really small script, or this is a one-off script, then I will not make
you write a couple of tests. Anything other than that could really
benefit from some test scripts. Test::Harness makes this so simple
that you really have no excuse not to do it. If you do not have the
time, perhaps you are wasting too much time debugging scripts without
tests. MakeMaker is just not for modules after all.
- Did you talk to the bear?
-
Explain your problem aloud. Actually say the words.
-
For a couple of years I had the pleasure of working with a really good
programmer who could solve almost anything. When I got really stuck I
would walk over to his desk and start to explain my problem. Usually
I didn't make it past the third sentence without saying ``Never
mind---I got it''. He almost never missed either.
-
Since you will probably need to do this so much, I recommend some sort
of plush toy to act as your Perl therapist so you do not annoy your
colleagues. I have a small bear that sits on my desk and I explain
problems to him..
- Does the problem look different on paper?
-
You have been staring at the computer screen, so maybe a different
medium will let you look at things in a new way. Try looking at
a print-out of your program.
If you don't want to use dead trees, try looking at the source without syntax highlight, or even in a different editor. Change up the way it looks and the fonts you use so you see different patterns.
- Have you watched The Daily Show with Jon Stewart?
-
Seriously. Perhaps you do not like Jon Stewart, so choose something
else. Take a break. Stop thinking about the problem for a bit and
let your mind relax. Come back to the problem later and the fix may
become immediately apparent.
- Have you packed your ego?
-
If you still have not made it this far, the problem may be
psychological. You might be emotionally attached to a certain part of
the code, so you do not change it. You might also think that everyone
else is wrong but you. When you do that, you do not seriously
consider the most likely source of bugs---yourself. Do not ignore
anything. Verify everything.
--
brian d foy <bdfoy@cpan.org>
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.
|
|