PHP5 and NON-exceptional error handling
| From: | Greg Beaver | Date: | Fri, 09 Jun 2006 04:04:56 +0000 |
| Subject: | PHP5 and NON-exceptional error handling | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-42873@lists.php.net to get a copy of this message | ||
Hi all,
We have a problem. I believe Arnaud's simple sentence "if you use
exception, use PEAR_Exception" solves one half of the problem, as we all
know what to do when exceptional situations arise. However, it is
obvious that not all errors are exceptional, some are just expected in
the normal course of development, and bubbling up would get in the way
(i.e. Lukas's example).
For those who choose not to use exceptions, we still need to provide a
consistent interface for users to depend upon for their error handling.
Instead of requiring PEAR_Error, it would be wise to require that users
use some kind of error handling that implements a standardized
interface. In this way, end users can depend on certain functionality,
and developers are not limited in their ultimate choice of how to do the
actual errors.
There seems to be three ways of doing non-exceptional error handling:
1) directly return an error code from the function that encounters the
error message
2) log the error to some external data store
3) pass the error to a callback that would normally return control to
the line following the error condition.
PEAR_Error and PEAR_ErrorStack optimize different aspects of these three
tasks. PEAR_Error focuses primarily on #1 and #3, whereas
PEAR_ErrorStack focuses on #2 and #3.
I think we can support and standardize these three different models via
a set of interfaces that must be implemented by a
non-PEAR_Exception-based error handling/raising solution.
Here are some possibilities:
for #1:
interface PEAR_ReturnableError
{
function getCode();
function getMessage();
function toException();
function getTrace();
function getSeverity();
function __toString();
}
for #2:
interface PEAR_LogError
{
function setLogFile($file);
function setStream($stream);
function setVar(&$var);
}
for #3:
interface PEAR_CallbackError extends Subject
{
}
The first interface would be useful for methods/functions that return an
error object. One would need only add:
<?php
$ret = $blah->someMethod();
if ($ret instanceof PEAR_ReturnableError) {
...
}
?>
after calling a function/method
The last two would be directly implemented by the class. In this way,
you could (for instance):
<?php
$a = new PEAR_PHP5plus_Widget;
if ($a instanceof PEAR_LogError) {
$a->setLogFile('/path/to/error.log');
}
class observeit implements Observer
{
function update(Subject $subject)
{
if ($subject instanceof PEAR_ReturnableError) {
// do something with it
}
}
}
if ($a instanceof PEAR_CallbackError) {
$b = new observeit;
$a->attach($b);
}
?>
Of course, you may have noticed that PEAR_Exception is a
PEAR_ReturnableError (except it doesn't have a getSeverity() method).
This also allows using PEAR_Exception as a PEAR_Error-like thing, but
would allow implementation of a customized solution for a particular
project.
Comments?
Greg