brians Guide to Solving Any Perl Problem: Appendix B - Mastering Perlby brian d foy
This excerpt is from Mastering Perl.
This is the third in O'Reilly's series of landmark Perl tutorials, which started with Learning Perl, the bestselling introduction that taught you the basics of Perl syntax, and Intermediate Perl, which taught you how to create re-usable Perl software. Mastering Perl pulls everything together to show you how to bend Perl to your will.
After several years of teaching Perl and helping other people solve their Perl problems, I wrote a guide that showed how I think through a problem. It’s appeared on a couple of web sites and there are even a couple of translations.Some of the stuff I did unconsciously, and those are the hardest things to pass on to a new programmer. Now that I have this guide, other people can develop their own problem-solving skills. It might not solve all of your Perl problems, but it’s a good way to try.
- 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’ve all been there.
- Personal responsibility
If you have a problem with your program 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 programs, 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 won’t. Adapt to Perl. It is just a language, not a way of life.
- Does your program compile with strictures?
If you aren’t 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
perl -Mstrict program.pl
You may be annoyed at strictures, but after a couple of weeks of programming with them turned on, you’ll write better code, spend less time chasing simple errors, and probably won’t need this guide.
- What is the warning?
Perl can warn you about a lot of questionable constructs. Turn on warnings and help Perl help you.
You can turn on warnings from the command line:
$ perl -w program.pl
Lexical warnings have all sorts of interesting features. See the
warningspragma documentation for the details:
If you don’t 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:
- Solve the first problem first!
After you get error or warning messages from
perl, fix the first message then see if
perlstill 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
perlgets worried, the problem has already occurred and the line number
perlis on may actually be after the problem. Look at the couple of expressions before the line number in the warning.
- Is the value what you think it is?
Don’t guess! Verify everything! 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";
$valuein brackets so I can see any leading or trailing whitespace or newlines. If I have anything other than a scalar, I use
Data::Dumperto 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
-dswitch. See perldebug for details:
perl -d program.pl
You can also use other debuggers or development environments, such as ptkdb (a graphical debugger based on Tk) or Komodo (ActiveState’s Perl IDE based on Mozilla). I cover debugging in Chapter 4, Debugging Perl.
- 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
perldoccommand and its
perldoc -f function_name
If you’re 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
- 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 installed module version with a simple
perl -MModule::Name -le 'print Module::Name->VERSION';
- Have you made a small test case?
If you’re 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 isn’t in that code. If the program doesn’t do what you think it should, 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 already 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::SmallProfdo the heavy lifting for you. It counts the times
perlexecutes a line of code as well as how long it takes and prints a nice report. I cover profiling in Chapter 5, Profiling Perl.
- 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 program or this is a one-off program, then I’m not going to make you write a couple of tests. Anything other than that could really benefit from some test programs. The
Test::Moremodule makes this extremely simple, and if you program your script as a modulino as in Chapter 18, Modules As Programs, you have all the tools of module development available for your program.
- 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 wouldn’t make it past the third sentence without saying, “Nevermind—I got it.” He almost never missed either.
Since you’ll probably need to do this so much, I recommend some sort of plush toy to act as your Perl therapist so you don’t annoy your colleagues. I have a small bear that sits on my desk and I explain problems to him. My girlfriend does not even pay attention when I talk to myself anymore.
- 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 printout of your program.
- 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’ve have 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 don’t seriously consider the most likely source of bugs—yourself. Do not ignore anything. Verify everything.
If you enjoyed this excerpt, buy a copy of Mastering Perl