Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Exception naming for 2.0 Component Proposal

Proposed Component Name Exception naming for 2.0
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Exception naming for 2.0
Proposers Jurriën Stutterheim
Zend Liaison TBD
Revision 1.0 - 03 June 2008: Initial Draft. (wiki revision: 5)

Table of Contents

1. Overview

This proposal describes an idea for naming conventions for exceptions. There is also a proposal about component naming, but it seemed that this would not fit in well with that proposal.

Currently there is an exception class per component and possibly per part of that component. E.g. Zend_Component_Exception and Zend_Component_Part_Exception. This approach poses a few problems.
The first is that it is currently not possible to catch specific exception in a catch block. This problem is partially tackled by the Exception codes in exceptions proposal. However, this still requires a switch block to sort out which exception was thrown. Please note that this proposal is not a replacement for the exception code proposal. The exception code proposal can be very beneficial for this proposal as well.
The second problem is that exception classes are scattered between the rest of the classes, where they don't really belong.

Instead a propose to follow a more conventional ways of naming exceptions. The name of the exception class would already provide some info of what the problem might be. Also, separate catch blocks could be made to separate different kinds of logic per exception. The way this proposal suggests naming these classes would also arrange for exception classes would be grouped together in a directory.

To maintain some BC and to make it possible to catch an unspecified exception for an entire component, a Zend_Component_Exception class could remain.

In case of Zend_Config, some possible exception classes could be the following:

As you can see, all exceptions are collected in one folder. Now if I want to create a config and I want to be able to handle exceptions, I can write something like this:

But if I wanted to just catch any exception thrown by Zend_Config, I could just do it the old-fashioned way:

Usage with PHP 5.3 namespaces
The exception names proposed above are for the current way of using pseudo-namespaces in ZF. When ZF switches to use PHP 5.3's namespaces, there should be an exception namespace inside the component namespace.
The exception class could look something like this:

This would translate to Zend::Config::Exception::ReadOnlyException, or when using the "use" statement, just ReadOnlyException.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

4. Dependencies on Other Framework Components

5. Theory of Operation

6. Milestones / Tasks

7. Class Index

8. Use Cases

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jun 13, 2008

    <p>I agree with you.</p>

  2. Jun 18, 2008

    <p>The idea behind this is good. The implementation would be as problematic as with my and Matthews Exception Code proposal.</p>

    <p>It would be nice if you finish the proposal so it will be reviewed additionally with our proposal.<br />
    As both propose a needed BC break within exception it would be needed to have the ok and probably also the work done WITH 2.0</p>

  3. Jun 20, 2008

    <p>ZF will adopt PHP namespacing at some point- maybe even when we release 2.0. With namespacing, it is hardly ideal to have a bunch of classes named 'Exception', even if they are in different packages. This is solved in other languages by being more specific about the exception in the class name. I think your proposal won't work well with namespaces because you'd end up with classnames like 'Exception' and 'ReadOnly'. As an example, the second exception should probably be named 'ReadOnlyException' instead.<br />
    I <strong>strongly</strong> recommend you refactor this proposal to work well with namespaces, otherwise it is unlikely to get the support of the Zend team and the broader community.</p>

    <p>,Wil</p>

  4. Aug 18, 2009

    <p>This proposal is largely superceded by the Exception conventions we will be adopting when we move to 2.0 (and which are recommended going forward).</p>

    <p>These conventions propose that each component have a marker interface named "Exception", and exception classes that implement it and extend various SPL exceptions (including the primary Exception class itself). Such classes should end with the word "Exception".</p>

    <p>As an example:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    namespace Zend\Controller;

    interface Exception
    {
    }

    abstract class PageNotFoundException extends \Exception implements Exception
    {
    }

    class ActionNotFoundException extends PageNotFoundException
    {
    }

    class ControllerNotFoundException extends PageNotFoundException
    {
    }

    class InvalidArgumentException extends \InvalidArgumentException implements Exception
    {
    }
    ]]></ac:plain-text-body></ac:macro>

    <p>This allows you to catch Zend\Controller\Exception – or any of the SPL exceptions, etc. It also allows for more fine-grained naming of exceptions so as to avoid the need to use messages and/or codes.</p>

    <p>As this is the future direction for exceptions already, I'm going to archive this proposal.</p>

    1. Jun 22, 2010

      <p>The regular directory with the code making world better is filled with (almost always) empty Exception classes this way! That is what I see in the temporary git repo for zf2 now. How about using another approach:</p>

      <p>In application code you throw an exception like this:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      namespace App\Router;

      class Router
      {
      public function foo()

      Unknown macro: {    throw new ExceptionSocketCreate( 'Cannot create socket' ); }

      }
      ]]></ac:plain-text-body></ac:macro>

      <p>In the separate "Exception" folder there are all the exception files laying down. Inside this classes you see</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      namespace App\Router\Exception;

      class SocketCreate extends Exception
      {
      }
      ]]></ac:plain-text-body></ac:macro>
      <p>And the class that was extended</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      namespace App\Router\Exception;

      class Exception extends \Exception implements Exception
      {
      }
      ]]></ac:plain-text-body></ac:macro>
      <p>When you use this code you know that there are exceptions all in a single folder, you can take a look at what exceptions this component throws just by taking a look at the folder structure.</p>

      <p>in the code using this component:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      use App\Router\Exception;

      try
      {
      $router->foo();
      }
      catch( Exception\ServerNotAlive $e )
      {
      do your stuff
      }
      ]]></ac:plain-text-body></ac:macro>
      <p>Or even with the whole namespace provided:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      try
      {
      $router->foo();
      }
      catch( \App\Router\Exception\ServerNotAlive $e )
      {
      do your stuff
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>This way directory structure is much more logical and easy to work with. I'm using this in my project and this seems to be very convenient.</p>

      1. Jun 23, 2010

        <p>+1</p>

        <p>I like it to have all exceptions on a separate folder!<br />
        Some components have a lot of different exceptions. If there are all at the components base level it gets illegible.</p>

        <p>The following structure is more readable:<br />
        (ordered by filename like a file explorer)</p>
        <ul>
        <li>Zend\Cache\Exception (interface)</li>
        <li>Zend\Cache\Exception\BadMethodCall (class)</li>
        <li>Zend\Cache\Exception\Exception (interface)</li>
        <li>Zend\Cache\Exception\InvalidArgument (class)</li>
        <li>Zend\Cache\Exception\IO (class)</li>
        <li>Zend\Cache\Exception\Runtime (class)</li>
        <li>Zend\Cache\Exception\UnknownOption (class)</li>
        <li>...</li>
        <li>Zend\Cache\Pattern (interface)</li>
        <li>Zend\Cache\PatternFactory (class)</li>
        <li>Zend\Cache\Storage (class)</li>
        <li>...</li>
        </ul>

        <p>than this:</p>
        <ul>
        <li>Zend\Cache\BadMethodCallException (class)</li>
        <li>Zend\Cache\Exception (interface)</li>
        <li>Zend\Cache\InvalidArgumentException (class)</li>
        <li>Zend\Cache\IOException (class)</li>
        <li>Zend\Cache\Pattern (interface)</li>
        <li>Zend\Cache\PatternFactory (class)</li>
        <li>Zend\Cache\RuntimeException (class)</li>
        <li>Zend\Cache\Storage (class)</li>
        <li>Zend\Cache\UnknownOptionException (class)</li>
        <li>...</li>
        </ul>

        <p>But this looks like an error:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        namespace App\Router\Exception;

        class Exception extends \Exception implements Exception
        {
        }
        ]]></ac:plain-text-body></ac:macro>
        <p>It could be written as:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        namespace App\Router\Exception;
        use App\Router\Exception as RouterException;

        class Exception extends \Exception implements RouterException
        {
        }
        ]]></ac:plain-text-body></ac:macro>

        1. Jun 24, 2010

          <p>That was an error. But why does Exception need to implement anything? Why not Exception simply to extend \App\Router\Exception\Exception which extends \Exception and that is all ? If \App\Router\Exception\Exception is an interface it should be named as \App\Router\Exception\ExceptionInterface I suppose. Not so beauty.</p>

          1. Jun 24, 2010

            <p>Please read the Zend Framework 2.0 Roadmap for Exceptions incl. Matthew's comments <ac:emoticon ac:name="wink" /></p>

            <blockquote>
            <p>First off: this use case actually did not originate with myself or the Zend team, but was one brought up and agreed upon during the original PHP project interoperability group meeting at php|tek in 2009. If we don't do this, we'll be operating differently than other frameworks - which makes that particular point of yours moot.</p>

            <p>The rationale is clearly described in the narrative, but I'll bring up the salient points:</p>
            <ul>
            <li>It allows catching the exception as an SPL/native Exception</li>
            <li>It allows catching the exception as a specific vendor/component/subcomponent exception</li>
            <li>It encourages creation of well-defined and descriptively named exceptions</li>
            </ul>
            </blockquote>