Re: Exception misinformation
| From: | Justin Patrin | Date: | Tue, 06 Jul 2004 23:07:15 +0000 |
| Subject: | Re: Exception misinformation | ||
| References: | 1 2 3 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-31680@lists.php.net to get a copy of this message | ||
On Tue, 06 Jul 2004 18:55:00 -0400, Hans Lellelid <hans@velum.net> wrote:
> Hi Justin,
>
> Some good comments here -- and indeed your example below highlights some
> challenges.
>
>
> > They're not fatal, but they do have Fatal tendencies. To react well to
> > an error with Exceptions, there may have to be many try/catch blocks.
>
> Ok, fair enough. Remember too, though, that you can
> set_exception_handler() to have a nice error if all else fails -- e.g.
> redirect to error page if it's a web application. Doesn't really change
> the fact that the error was fatal, but considering there wasn't any docs
> for set_exception_handler() last I looked, it probably needs mentioning.
>
Well, that would be a nice addition. There really should be a PHP5
manual out there in parallel with the PHP4 manual. Or at least all
PHP5 functions should be in the manual as PHP5 only. Although an
outside try/catch would be the same, right?
>
> > I had never considered this before. This is a very nice thing, and
> > would not be possible to fix, even with my Exception or Error
> > proposal.
>
> Yes, i think this is the main reason why exceptions are great. The
> immediate jump to catch block is good (well, I think so), but the bubble
> up is ingenious. That said, it should be an obligation of your code to
> explicitly declare that exceptions may bubble through.
>
> > Yes, I agree. But it is nice to have the ability to simply ignore
> > errors sometimes and see what the program does overall. With
> > Exceptions, that's not possible without lots of extra try/catch
> > blocks.
>
> I'll grant that it is harder to have error just ignored when you are
> throwing them. You can ignore errors but it takes more work, that's
> true. I would still argue that having a system that forces handling is
> going to eliminate far more headache in the long run.
>
Yes, this is true. It just makes rapid prototyping a little harder.
Not much, though.
> >>4) No one is suggesting throwing WARNING or NOTICE exceptions. Warnings
> >>and notices deserve their own handling system (or trigger_error()).
> >>These have very little in common with exceptions, which are errors that
> >>need to be *handled* by the calling code.
> >>
> >
> >
> > Although I rarely if ever see WARNINGS and NOTICES in PEAR packages.
> > All errors are Errors.
>
> Yup, me neither. I think warnings/notices is fairly insignificant. Not
> that many apps use warnings/notices & not that many calling apps care.
>
> > [snip]
> >
> >>Hopefully that illustrates that it is never harder to catch or throw an
> >>exception than it is to handle a return-code error. Feels silly to
> >>explain this, but I do think many people need to see more examples of
> >>this stuff (and perhaps use it!!).
> >
> >
> > Yes, it's no harder to use. It *can* make code harder to follow, though.
>
> Yes, that is true; it can be harder to follow. Good documentation is
> definitely a strong requirement for any package that uses exceptions.
>
> > This is a point that *must* be talked about. Especially "using
> > exceptions as flow control". What does this mean exactly? Let's say
> > that a package throws a file not found exception. Perhaps I want to
> > try another file (or group of files), meaning a loop in the code based
> > on whether an exception is caught. This is pretty ugly. But the file
> > not found exception is an error and therefore an exception for the
> > class I'm calling.
>
> Yes, here I think you've identified the place where things get really
> tricky. This logic is very hard to handle using Exceptions and can
> sometimes be very kludgy. Also, I would agree that this is using
> exceptions as error handling. In most cases faced with such a scenario
> I would say that it needs to be redesigned.
>
> Also, I would point out that using PEAR::isError($obj) with if/then/else
> statements is really still using error handling as flow control, and
> shouldn't be considered "ok" while try/catch is "bad".
>
> The immediate thing that leaps to mind is that you should "look before
> crossing the street" (I made that up, but it seems to fit :) I think
> that you agree with me (below), but I'll illustrate, anyway:
>
> i.e.
>
> $file = array_shift($files);
> while(!file_exists($file)) $file = array_shift($files);
> // this isn't 100% correct, but you get idea
>
> $pkg->performAction($file);
>
> In general, by checking things more thoroughly you can avoid many of
> these issues.
>
Yes, this would be the right way for files, but you saw my example
below, which is a better one.
> > Or say that if a file isn't found, I want to switch to an alternate
> > method of getting the information I need?
> >
> > If file not found is too easy to get around for you (file_exists),
> > then consider trying to connect to an FTP server. If it fails, use a
> > file on the filesystem, or possibly us eanother method. If the FTP
> > class throws an exception, I'm forced to use that exception to change
> > the flow of my code. There is simply no way of getting around that.
>
> Well, that does further complicate things :) -- getting into some
> pretty fring cases here, but it's a good challenge.
>
> In this case you do kinda have to use exceptions as flow control since
> you actually are basing your logic on errors.
>
> Well, on the other hand, you could probably design your code in such a
> way so that you didn't have to use nested try/catch blocks. For
> example, identify that what you are describing is a number of loading
> mechanisms for a particular file resource. Create different strategy
> classes for the different ways that this file can be loaded:
>
> $loaded = false;
> while(!$loaded) {
> try {
> $strategy = array_shift($loadingStrategies);
> $strategy->load($file);
> $loaded = true;
> } catch (Exception $e) {}
> }
Yes, I thought of this as well. Yours would loop forever if none that
worked, though. Maybe something like this:
$loaded = false;
$strategy = true;
$exceptionMessages = '';
while(!$loaded && $loadingStrategies) {
try {
$strategy = array_shift($loadingStrategies);
$strategy->load($file);
$loaded = true;
} catch (LoadingException $e) {
$exceptionMessages .= $e.getMessage();
}
}
if(!$loaded) {
throw new LoadingException('No loading strategies worked.
'.$exceptionMessages);
}
--
DB_DataObject_FormBuilder - The database at your fingertips
http://pear.php.net/package/DB_DataObject_FormBuilder
paperCrane --Justin Patrin--