SPUG: Re: IO::All
ingy at ttul.org
Sat May 29 17:20:44 CDT 2004
On 24/05/04 21:35 -0700, ced at carios2.ca.boeing.com wrote:
> Difficult problem. I/O errors, though, tend to be dealt with very
> unevenly. We religously check 'open' succes but then assume 'print',
> etc. succeed. I try to emulate T. Christiansen's paranoia:
> From the Perl Cookbook:
> When opening a file or making virtually any other system call,
> checking the return value is indispensable. Not every open succeeds;
> not every file is readable; not every piece of data you print can
> reach its destination. Most programmers check open, seek, tell, and
> close in robust programs. You might also want to check other functions.
> When you no longer have use for a filehandle, close it.... implicity
> closes are for convenience, not stability, because they don't tell
> you whether the system call succeeded or failed.
> I recall once a 'close(FH) or die $!' revealed a full file system.
> This was a critical monitoring app so I was really thankful for
> having heeded Tom's quiet crusade.
Good advice, and bad advice at the same time. I'm not overly keen on
overly defensive programming. It creates crufty code. When I look at
code I always want to be looking at the important stuff, not the edge
case stuff. So I tend not to write a lot of edge case stuff in my code.
At least until I get bitten. It's about avoiding premature optimization.
But then, even if I need to add error checking code, I'll want to put it
somewhere where I'll never see it again. That's why we have living rooms
and garages. I would feel embarrassed to have guests over with error
checking code all over my living room floor. So I chuck it in the
IO::All could be a garage. I could check for every possible error in
IO::All for you, so you would never need to worry. But maybe that would
cause problems. For instance should I throw an exception if a system
close() fails? Maybe, maybe not. Does Perl throw an exception? No. Does
it warn? No. Why not? I'm not sure. But from talking to the old timers,
their advice is that a module should never die. In Perl you just keep
going until something gives out. (Python will die if you even look at it
funny. Die first, ask questions later.)
I take this advice with a gram of salt though. If you know the user made
a common mistake and couldn't have possibly got a good result, just die.
She can catch the die if she really wants to.
So in IO::All I check for errors that have bitten me. I always throw the
errors with a throw method. That way I can override how the error is
handled. The default is to call Carp::croak. In the latest version of
IO::All I added a confess method:
$stuff < io('xyz')->confess;
This method just tells throw to call the more vigorous Carp::confess
when there is an error. There is also an errors method:
$stuff < io('xyz')->errors(\&handle_errors);
This gives just a little bit of control. I suppose I could add levels of
$io = io('xyz')->strict;
$io = io('xyz')->silent;
I probably will do that at some point.
But the whole point of IO::All is to write cleaner code. If you are a
real control freak, maybe IO::All isn't right for you. But then maybe
again Perl isn't right for you. I've met many people who just couldn't
use a language like Perl Python or even Java because of the the control
they'd give up by not using C. And I've met so folks who couldn't move
past assembler to get to C. From my point of view, Perl was a decent
step forward, but it still leaves a lot to be desired. That's why I'm
fixing it. :)
More information about the spug-list