Re: My Experience with PHP5 Error Handling (and possible
| From: | Justin Patrin | Date: | Thu, 26 Aug 2004 04:43:11 +0000 |
| Subject: | Re: My Experience with PHP5 Error Handling (and possible | ||
| References: | 1 2 3 4 5 6 7 8 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-32953@lists.php.net to get a copy of this message | ||
On Wed, 25 Aug 2004 21:09:25 -0400, Davey <davey@php.net> wrote:
> Greg Beaver wrote:
> > Alexey Borzov wrote:
> >
> >> Greg, sorry, but I understand "PEAR_ErrorStack geared towards
> >> exceptions" as "Let's make it easier to ignore errors, exceptions are
> >> bad as it's difficult to ignore them".
> >
> >
> > Put simply: your understanding is both false and annoying. I have
> > stated repeatedly that I both use exceptions in my own php5 code, and
> > that I agree with everything in the RFC. I have also stated that I
> > didn't think the RFC goes far enough, and then even provided a way to
> > ensure that the RFC doesn't lock us down into something premature
> > through the idea of giving it a stability like packages. I have never
> > said that I didn't want to use exceptions, only that we need more
> > experience actually using them before we pin down how they *must* be
> > used. I've also stated that Exceptions, although useful, do not solve
> > absolutely every error-handling problem, and have posted these concerns
> > in the wiki page. Somehow, none of them made it into the RFC.
> >
> > 1) handling multiple error conditions at once is very difficult with
> > exceptions, and will need to be standardized
> > 2) upgrading warnings to exceptions and downgrading exceptions to
> > warnings is not difficult, but will be if it is not standardized.
> >
> > Your attack above is completely unfounded and has LITERALLY nothing to
> > do with either what I've said or my code.
> >
> >>> There is no "PEAR_Error-like abomination" here aside from
> >>> inflammatory rhetoric that serves no useful or even useless purpose.
> >>
> >>
> >>
> >> There *is*: adding cruft to the 'throw' will force people wanting to
> >> use PEAR packages use their idiosyncrasies of error handling. We'll
> >> have another incarnation of monstrous PEAR.php for which PEAR was
> >> bashed for quite some time, instead of getting rid of it completely.
> >
> >
> > If you can provide a single line of php that successfully backs up this
> > claim, I will fall over backwards in surprise.
> >
> > First of all, end-users would not see any difference in exception
> > handling if the package uses PEAR_ErrorStack as well. Why?
> > PEAR_ErrorStack Does Not Replace Exceptions, And Never Was Intended To
> > Do So (TM). How many friggin times must I say this people? End users
> > will ONLY see exceptions bubbled up from throw(). Any potentially
> > ignorable conditions will be on the error stack, and users will want to
> > deal with them, but since they are on a stack, the error handling can
> > happen separate from the logic - just like exceptions.
> >
> > The only potential difference inside a package would be if a developer
> > wishes to throw an exception and also store it on the stack. Why would
> > a developer want to do this? The only reasoning I can think of would be
> > to take advantage of unified logging. As I have said in the past, I
> > think that a unification of PEAR_Exception and PEAR_ErrorStack ideas
> > would work nicely. Why can't both share the same log?
> >
> > PEAR_ErrorStack::push() returns an Exception object in php5, and a
> > developer *may* choose to throw this object. Where the hell is the cruft?
> >
> > PEAR_ErrorStack can be used with older php4 packages to ease the
> > transition to replacement packages for applications.
> >
> > My statement "PEAR_ErrorStack geared towards exceptions" was clearly
> > defined in a previous mail that you conveniently ignored. I have
> > defined it again for your convenience. Please don't ignore this one.
> >
> > Currently, here is how PEAR_ErrorStack works:
> >
> > in php4, push() returns an array, and error info is stored internally as
> > an array.
> > in php5, push() returns an exception, and error info is stored
> > internally as an array.
> >
> > The advantage of this approach over storing an object, as I saw it, was
> > that the error info was simply data, and didn't force any particular
> > implementation of error stuff the way PEAR_Error does.
> >
> > My plan (which I have already said) was to re-tool PEAR_ErrorStack to be
> more friendly to warnings and in particular, to store error information
> > using Exception class names instead. This is because the class name can
> > replace both the package and error code fields, simplifying the API
> > substantially, and allowing easy promotion of a warning.
>
> How will this work in PHP4? Also, I don't see how the class name can
> replace the error code unless you have a seperate exception class for
> every error.
>
> I have my exceptions setup like this:
>
> abstract Crtx_Exception {
>
> const CRTX_EXCEPTION_ERROR = 1;
> const CRTX_EXCEPTION_WARNING = 2;
> const CRTX_EXCEPTION_NOTICE = 3;
>
> public __construct($msg, $code) {
> parent::__construct($this->getMsg($msg), $code);
> }
>
> protected function getMsg($msg, $code) {
> // an array of messages like:
> $msg[self::CRTX_EXCEPTION_ERROR] = "Fatal Error: $msg";
> return $msg[$code];
> }
>
> // Added for use with my afforementioned Crtx_ErrorStack
> public function getLevel($code) {
> // an array of levels like:
> $level[self::CRTX_EXCEPTION_ERROR] = 'error';
> return $level[$code];
> }
> }
>
> I then extend for each package, adding extra constants and overriding
> getMsg/getLevel as necessary (i.e. Crtx_SOAP_Exception or
> Crtx_XML_XSLT_Exception).
>
> The only way I can see to get the code, is $exception->getCode() - is
> this what you mean?
>
> Like I've tried to impress on certain people, If you're writing a PHP 5
> only package you will do:
>
> class Some_Package5 {
> public function __construct() {
> if ($something_wrong) {
> throw new PEAR_Exception(...);
> }
> }
> }
>
> If you're writing a PHP4 packagte, you will do:
>
> class Some_Package4 {
> function Some_Package() {
> if ($something_wrong) {
> return PEAR::raiseError(...);
> /*
> On PHP4 this will return a PEAR_Error, and place it on the
> ErrorStack
> On PHP5 this will return null, and place it on the stack
> (this is completely PHP4 compatible and won't require an eval('throw foo');
> */
> }
> }
> }
>
> // if the user is creating PHP5 only code he can do:
>
> try {
> $obj = new Some_Package5;
> $obj2 = new Some_Package4;
> }
> catch (PEAR_Exception $e) {
> // handle it
> }
2 things:
1) If PHP5 only code throws exceptions as normal, *how* is this
different from the RFC? The RFC is about PHP5-only packages.
2) If the above Some_Package4 is a PHP4 compatible package, how will
the catch be of any use when there is no "eval throw" as you say?
I realize you're giving the option of using exceptions *or* ErrorStack
for PHP5 packages, but this either: 1) won't work or 2) makes work
harder for developers.
1) is true if what you mean is that a special method in the error
stack will either throw or put the error on the stack depending on a
configuration option. This has been discussed many times over (I was
the first to propose this AFAIK) and won't work because it breaks (or
makes extremely nasty) bubble-up and transaction-level error checking.
2) is true if what you means is: a package developer can choose to
throw exceptions or place errors on the stack. this means that there
are two error handling standards for PEAR. Using one package of each
error handling scheme means you have to check for errors in two ways.
It also means that PEAR has to support two different error handling
schemes and the user of these two packages has to include code to
handle both of these error handling schemes.
Both of these options fracture the error handling in PEAR in make it
harder for others to use it. It is much better IMHO to choose *one*
type of error handling and stick with it. I and many others have been
persuaded that Exceptions are the way to go. The vote on the RFC is
what will decide whether this way will be what we use.
If you had these major issues, you really should have brought them up
during the weeks that were spent filling up the wiki and commenting on
the RFC. Why did you and others wait until the voting started to start
the same arguments over again?
>
> // he can also do the below :)
>
> /* if the user is creating code for PHP5 that uses PHP4 packages (note
> you CANNOT use PHP5 classes in PHP4, thats not the point of my idea!) he
> will do: */
>
> $obj = new Some_Package5;
> $obj2 = new Some_Package4;
>
> if (PEAR_ErrorStack::staticHasErrors('Some_Package5') ||
> PEAR_ErrorStack::staticHasErros('Some_Package4')) {
> // handle it
> }
>
> /* if the user is creating code for PHP4 only, he can't use Some_Package5 */
>
> $obj = new Some_Package4;
>
> if (PEAR::isError($obj)) {
> // handle it
> }
>
> OR
>
> if (PEAR_ErrorStack::staticHasErrors('Some_Package4')) {
> // handle it
> }
>
> So you see, the user only needs to compromise exceptions when either:
> a) Working with PHP4 only
> b) using PHP4 packages in PHP5
>
> If he is doing:
> c) using PHP5 packages in PHP4... it won't work
> or
> d) Using PHP5 packages in PHP5 only app, he will just use try...catch IF
> HE WANTS
>
> I hope this FINALLY explains things...
>
> - Davey
>
--
DB_DataObject_FormBuilder - The database at your fingertips
http://pear.php.net/package/DB_DataObject_FormBuilder
paperCrane --Justin Patrin--