Re: Re: PEAR2 Standards Update
| From: | Chuck Burgess | Date: | Tue, 22 Sep 2009 18:54:27 +0000 |
| Subject: | Re: Re: PEAR2 Standards Update | ||
| References: | 1 2 3 | Groups: | php.pear.dev php.standards |
| Request: | Send a blank email to pear-dev+get-52887@lists.php.net to get a copy of this message | ||
On Tue, Sep 22, 2009 at 12:47 PM, Michael Gauthier <mike@silverorange.com>wrote:
> On Tue, 2009-09-22 at 18:42 +0200, till wrote:
> > On Tue, Sep 22, 2009 at 5:38 PM, Brett Bieber <brett.bieber@gmail.com>
> wrote:
> > > Greetings everyone -
> > >
> > > Just an update on PEAR's progress adopting the "PHP Standards and Best
> > > Practices for PHP 5.3+ Frameworks and Libraries." :-)
> > >
> > > At the last PEAR Group meeting the exception policy and the class
> > > naming policy were approved by the PEAR Group and are now incorporated
> > > into the PEAR2 standards.
> >
> > I got a couple questions -- and I looked at the docs.
> >
> > Currently, a couple packages implement/use SPL exceptions directly,
> > e.g. they throw an InvalidArgumentException and not
> > Foo_InvalidArgumentException. Does this mean we have to wrap all SPL
> > exceptions when we want to use them?
> >
> > Also, how exactly does that play with having a base exception class?
> >
> > My base exception class is Foo_Exception, but I want to use SPL
> > exceptions as well. How do I extend to conform to the rule to provide
> > one base exception for the package? From what it looks like, I extend
> > the SPL exception but implement my own package' base exception. I'm
> > not sure if I read the code right, so I'm asking to make sure.
>
> You are required to wrap SPL exceptions thrown by your package. The idea
> here is that all exceptions generated by a package can be caught using
> "catch foo\Exception $e".
>
> For example:
>
> class foo\InvalidArgumentException extends \InvalidArgumentException
> implements foo\Exception
> {
> }
>
> Cheers,
>
>
> Mike
>
I think this below sets up the strongest use case -- let's consider this set
of base package exception classes:
- class \foo\Exception extends \Exception {}
- class \foo\InvalidArgumentException extends \InvalidArgumentException
{}
- class \foo\OutOfBoundsException extends \OutOfBoundsException {}
Let's say I'm a package user who is only interested in catching this
package's exceptions generically, not trying to specifically watch for each
type of exception that the package could possibly throw. This means I want
the ability to catch them all from one *catch()* clause. Now, how can I
catch all three of these package exceptions above with one *catch()*? The
only way would be to *catch(\Exception)*, the global Exception, because
that's the only common parent class, right? \foo\InvalidArgumentException
doesn't extend from \foo\Exception, so *catch(\foo\Exception)* would not
catch it... the same applies to \foo\OutOfBoundsException.
I know that someone is going to think of "I could just *try {}
catch(\foo\Exception) {} catch(\Exception) {} *, but that's requiring the
package user to catch *everything*, not just exceptions from the package
alone. If you go with the base exception class along with exceptions
extending from SPL, then the only way the package user can catch "only the
package exceptions" is to explicitly catch every single type that you define
in your package.
The standard says to define them this way:
- interface \foo\Exception {}
- class \foo\InvalidArgumentException extends \InvalidArgumentException
implements \foo\Exception {}
- class \foo\OutOfBoundsException extends \OutOfBoundsException
implements \foo\Exception {}
Now, *catch(\foo\Exception)* could indeed catch both of those package
exceptions above.
A smaller edge case rationale for going with an interface instead is the
intersection of:
- user of package decides to subclass the package's exceptions
- maintainer of package decides to refactor the package's exceptions
This sets up a potential BC break, if you remove/modify your package's
exception classes at all. It boils down to being a safety net for the
benefit of the users of your package, I think.
I'm putting together a concrete code example, which I'll pass on shortly...
--
CRB