Semantic Coding?
What is sfException?
As the sfException phpDoc says: > sfException is the base class for all symfony related exceptions and provides an additional method for printing up a detailed view of an exception.
If you look at the code of sfException you’ll see that sfException has a bunch of tool to wrap an exception inside an sfException. That’s why when an exception of any kind is thrown in symfony, you see a nice html output.
In a symfony application, every thrown exception that bubbles up is eventually catched in the sfFrontWebController class. Then this exception is wrapped into an sfException one and is displayed to the user.
The catching mechanism
<?php try { // application running… […] } catch (sfException $e) { $e->printStackTrace(); } catch (Exception $e) { sfException::createFromException($e)->printStackTrace(); }
The wrapping mechanism
<?php static public function createFromException(Exception $e) { $exception = new sfException(sprintf('Wrapped %s: %s', get_class($e), $e->getMessage())); $exception->setWrappedException($e); self::$lastException = $e; return $exception; }
As you can see, sfException was created mainly to display a nice debug trace and not to replace ALL exceptions! Don’t worry to throw other exception php provides, there’s always be a nice debug trace! 😉
PHP provides a lot of different exceptions
PHP provides 2 predefined exceptions known as Exception and ErrorException.
Exception is the base class from where all other exceptions inherit from. ErrorException can be used when you want that PHP throws exception instead of reporting errors. For more information about ErrorException, you can read the dedicated documentation.
The Standard PHP Library (SPL) provides 13 more exceptions. These exceptions are: BadFunctionCallException, BadMethodCallException, DomainException, InvalidArgumentException, LengthException, LogicException, OutOfBoundsException, OutOfRangeException, OverflowException, RangeException, RuntimeException, UnexpectedValueException.
Each of these exception have a name that provide information on what the problem is which is pretty useful.
Now let’s use those exceptions and see how they improve the global readability (and scanability) of your code.
Semantic exceptions
Let’s read those two pieces of code.
This one with the uncool sfException everywhere:
<?php class Container { protected $maxItemCount = 2, $container = array(); public function addItem($item) { if (count($this->container) < $this->maxItemCount) { $this->container[] = $item; } else { throw new sfException('Cryptic long message saying container is full'); } } public function sliceItem() { if (empty($this->container)) { throw new sfException('Cryptic long message saying container is empty'); } array_slice($this->container); } }
And the cool one with semantic exceptions:
<?php class Container { protected $maxItemCount = 2, $container = array(); public function addItem($item) { if (count($container) < $this->maxItemCount) { $container[] = $item; } else { throw new OverflowException('Cryptic long message saying container is full'); } } public function sliceItem() { if (empty($container)) { throw new UnderflowException('Cryptic long message saying container is empty'); } array_slice($container); } }
In the second example, you don’t have to read the message to know what it’s all about. The name is sufficient. Furthermore, you’ll get more informations while scanning the code with correct exceptions name than with sfException everywhere.
More significative code = More readable code = More scannable code = Happy developer = Rainbows in kittens’ eyes.