in reply to if (ref $value eq "ARRAY") {

When I first started writing modules, I took a paranoid approach. The problem was, I had to get more and more paranoid as I discovered more and more variations of possible erroneous data input. My sanity checks turned more and more into insane checks.

After a while, I took a step back. This couldn't be it.

I thought about it and came to the conclusion that most of the time, if I'm given a totally wrong type of input (scalar when I expected a hashref, or something similar), it is a rare case that the program can recover gracefully. Most of the time it results in aborted execution one way or another. It may be a bit nicer if you give the caller a chance to clean up before he croaks, but essentially you can rarely deal with these errors in any other way than having the programmer fix the code, plain and simple.

Considering this, I decided to stick to semantic checks and leave the syntactical ones out. If I expect an arrayref, I may croak "not an arrayref" unless ref $param but won't go out of my way to ensure that it's really an arrayref. If I get a nonref and try to dereference it, Perl will die screaming. That's ok, we know something went wrong. I will however check whether scalar @$param reports the right number of elements, because that won't cause Perl to die screaming, it will simply make my code malfunction, leaving the user-programmer with no obvious clue about what went wrong.

The benefit is similar to all the other instances where Perl merely asks you to play by the rules rather than wielding a shotgun to force you to: I don't need to spend millenia coding sanity checks for every conceivable constellation under the sun, and in turn someone using my module can do something I didn't think of without having to spend millenia trying to trick my "sanity" checks.

Perl is laid back. Perl programmers should be laid back too. False paranoia is a waste of energy.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re(2): if (ref $value eq "ARRAY") {
by FoxtrotUniform (Prior) on Aug 24, 2002 at 00:19 UTC
      I thought about it and came to the conclusion that most of the time, if I'm given a totally wrong type of input (scalar when I expected a hashref, or something similar), it is a rare case that the program can recover gracefully.

    Even if you could recover gracefully from wrong input, it's probably a bad idea. If you get wrong input, then somewhere along the line someone screwed up, and about the worst thing you can do is hide the problem (or at least pass it on to another chunk of code further away from the original) and make it harder to debug. That sort of false "defensive programming" isn't just a waste of time, it's actively harmful.

    In general, I like to write code that fails -- gracefully, mind you, not locking up the machine or any such -- as soon as possible on bad assumptions. Makes it easier to find bugs.

    --
    F o x t r o t U n i f o r m
    Found a typo in this node? /msg me
    The hell with paco, vote for Erudil!

      That's what I was getting at. It's not actually possible to really recover from such errors in a sensible way, so I want to croak at some point anyway. Since Can't use string ("...") as an ARRAY ref is just as good as a custom croak message, I simplify my life by skipping checks for conditions that wil cause the code to blow up anyway. Instead I check for semantic problems where I need to hit the selfdestruct button myself because Perl won't know to do it for me.

      Makeshifts last the longest.