http://qs1969.pair.com?node_id=491430


in reply to Friendly error trapping

I need to put the best face on the error and keep the program going.
You mean, if the code tries to open an output file and this generates an error instead of succeeding, you just want to tell the user something like "this probably won't work as intended..." or "no output is being saved, but we'll go through the motions anyway...", and forge ahead? Somehow that doesn't seem like the right thing to want. (Maybe I misunderstood the question.)

IMO, a vital element in writing software for use by others is to anticipate, as much as possible and reasonable, what can go wrong during execution due to factors beyond the scope of the software -- such as "disk full" or hardware/permission issues that make it impossible to save output to a file.

Among the things thus identified, if you can differentiate things according to severity (e.g. things that really make execution pointless/doomed vs. things that just disable some features), it's great to provide distinct and appropriate handling for each case.

But in any case, either you have to trust your users' ability to heed and understand your error and warning messages, or else you have to set yourself up to do some hand-holding when then come back to you asking what your error and warning messages mean.

The behavior of the code in the face of unsuitable conditions needs to be appropriate to the seriousness of the problem (not to any notion of "saving face"), but more importantly, the errors and warnings generated by the code -- and the documentation that accompanies the code -- need to be clear enough, and provide enough detail (but not a bunch of irrelevant detail), so that the user can understand both the problem and what needs to be done about it (or at least, the user can easily relay the message to you or some other support programmer who can figure it out if the user is clueless).

If you're talking about an interactive process where you need to tell the user things like "I couldn't use that last output file name you provided because ... -- please try a different path or file name:", that's a question of providing the appropriate user interface.

You should have an underlying model of the user(s): what they know and understand, what information they need to provide in order to make the software work, and what will be, for them, the most effective and least troublesome way to provide that information. With that, the error handling should fall into place pretty naturally.

Replies are listed 'Best First'.
Re^2: Friendly error trapping
by monarch (Priest) on Sep 13, 2005 at 01:37 UTC
    The question made sense.

    dieing is the right response when something occurs in code that the programmer was not expecting or hasn't got around to handling.

    On the other hand, as graff points out, when an error condition can be anticipated then testing for that error and producing an alternative response is a great thing to do.

    For example, in a commercial web app, it is conceivable that a database handle may not be obtained (high load, some tweap in operations decided to take the db offline, sunspot interference). What to do in the situation.. die and leave the user hanging? No; probably a more adequate response is a "website is busy, please return back soon!". If the webpage just died then it would be particularly unpretty and unprofessional.

    Of course, if that multiline if..elsif..elsif.. statement falls through to a final else that should be impossible, then die and die spectacularly.. the programmer needs to urgently tend to the impossible!

Re^2: Friendly error trapping
by bradcathey (Prior) on Sep 13, 2005 at 02:17 UTC

    My question was simply this: is there something internal that die does that is necessary to exit a script properly?

    The very point of this is to provide a more detailed error message, such as you describe, so the user does indeed know what the problem is without ungraciously dumping them in the middle of nowhere.

    Update: To clarify, almost 100% of the time, this scenario is usually part of processing an HTML form which is uploading something or performing some file op, such as deleting a file. If there is an error, I use HTML::Template and HTML::FillInForm to re-display the form with the error message at the top so they can try again (or at least know what happened).


    —Brad
    "The important work of moving the world forward does not wait to be done by perfect men." George Eliot
      This sounds like the question centers on issues of application design and having some sort of understanding of the user.

      Regarding the conditions and information that the app needs in order to do its work for the user, you need to know by design what things are provided directly and explicitly by the user (command-line args, form parameters, dialog responses, maybe the contents of data files), and what things are determined by the OS/environment/config/etc (stuff that may be outside the user's control or awareness, including the contents of some data files). It can be easier to make the user understand the problem if they caused it and you can make that clear to them; if the problem stems from something other than their direct input, it might be harder to explain, but you should still try.

      As for tying up any "internal" loose ends before exiting a script "properly" in case of a problem, this really depends on what the app is doing. If you intend to keep running (e.g. retry by taking the user back to a point just before a bad input), you need to know what steps, if any, need to be undone, what inputs need to be rewound, and so on. It's a difficult issue to discuss in general terms.

      In any case, there's a good chance that users will find ways to break your code that you never thought of. Go ahead and give them some code to run anyway. Make some mistakes just like we all do, and if any particular problems vex you, come back with those.

      UPDATE: In response to this part of your question:

      Is it "safe" or "good practice" not to die? Or is there some intrinsic value of die that I am missing by not using it?
      The intrinsic value of "die" is to acknowledge that for certain conditions, further execution is useless and futile. That's the point of using "die". This can be "contextualized" within an eval block, so that you can trap a bad condition without actually halting execution of the whole script -- that is, by putting a "die" condition inside an eval block, you're saying "further execution within this block is pointless" (but on exiting the block, the main script can still decide what needs to be done next).

        Points well taken graff. I'm embarrassed to say, I have not used eval to trap errors. How about a little lesson here... if I were to trap the error in the OP would it look something like this?

        eval { uploader($dir, $name) }; print "There was a problem uploading your file: $@" if ($@); sub uploader { my ($upload_dir, $filename) = @_; ... open UPLOADFILE, ">$upload_dir/$filename" or die; }

        So, I can go ahead and die and the eval will trap and return the error without fatally terminating the script? Thanks!


        —Brad
        "The important work of moving the world forward does not wait to be done by perfect men." George Eliot