On Thu, May 2, 2013 at 6:00 PM, Adam Jon Richardson <adamj...@gmail.com>wrote:

> PHP currently has two separate approaches to handling errors:
> - Errors
> - Exceptions
>
> Both have their issues.
>
>
Just to clarify, PHP doesn't offer two separate approaches of handling
errors. We need to first distinguish between what is meant by a the terms
"Errors" and "Exceptions" so that we don't throw around ambigous claims
here. PHP has an error handler, which is where any part of your code can
send error reporting information to at any point in the execution stack.
This can be done both from user space as well as the core. PHP also has
Exceptions, but nothing in PHP's core throws Exceptions. They are normally
only used by extensions and classes, in user space, or those that extend
PHP.

So to be fair, PHP errors aren't really useful for user space error
handling. They're mostly informative. For example an E_NOTICE of Undefined
variable/index/offset just lets you know the variable/index/offset was not
defined within that scope up to that point. It doesn't really offer you any
way of handling that error since it's unlikely you would have a well
defined error handling path for it to that point. Which is where constructs
like isset() and/or empty() help you out. But this means the programmer has
to write their code with that error checking approach in mind. Just seeing
the error only informs of a potential for a bug. It can't really address
your requirements to handle application-level errors in that regard.

However, many PHP functions/classes do return different values to indicate
and error (some even offer additinoal error information such as
json_last_error, preg_last_error, PDO::errorInfo, etc...) where it makes
sense. So a function like json_encode will indicate failure by returning a
boolean false and a function like json_decode will indicate failure by
returning NULL. You have to go out and find the extended error information
yourself, but they will also send accompanying E_WARNING errors to the PHP
error handler to inform the user. Let's not get the purpose of using the
return value to test for failure and the purpose of the error handler
confused.


> Using and responding to errors requires that the returned value (if
> there is one) perform double duty as both a potential valid response
> AND, in the case of error, a flag that something went wrong. It's easy
>

This is all true, and I agree that this makes testing for error/failure
cases is convoluted in PHP.


> to forget to check that a particular call succeeded and specifically
> handle the error. I find myself constantly revisiting the
> documentation to ensure I know the specific error flag for functions,
> and performing post-hoc analysis of error logs to make sure I didn't
> miss an error flag that I would be better served by handling in the
> standard flow of my app.
>
> Using and responding to exceptions is a heavy-handed approach, as any
> particular exception can bring the entire application down.
> Additionally, the process of raising and catching exceptions loses
> context of the error, often requiring many different subclasses of
> exceptions to maintain the error state. Issues arise when the language
> constructs for exceptions are liberally used in situations that are
> not truly "exceptional," and where the the exception handling becomes
> a glorified goto.
>
> I've been programming in Go, and the ability to pass back multiple
> arguments, one of which is conventionally the error state, is
> wonderful. It's simple, clear, concise, and powerful. The code calling
> into the error-capable function knows the context and can handle
> errors appropriately according to the application requirements.
>
> In PHP, we could provide the ability to automatically pack up a
> comma-separated list of values as an array:
>
> return $var1, $var2;
> // returns [$var1, $var2];
>
> And, we could provide the ability to automatically unpack an array
> into separate variables:
>
> $var1, $var2 = myFunction();
> // same as list($var1, $var2) = myFunction();
>
> This functionality would allow us to embrace the convention that an
> error is passed back as one of the return values:
>
> $dbh, $err = db\connect();
> // check for error
> if ($err) {
>     // handle db connection error
> }
> // carry on normally
> $dbh->query("blah blah blah");
>
> The simplicity (just passing back values), clarity (the code to handle
> errors is proximal to the code that caused the error), and efficiency
> (not having to create bunches of exception subclasses to maintain
> context/information, and exceptions are expensive) of this approach is
> a beautiful thing. You can see an explanation of Go error handling
> here:
> http://blog.golang.org/2011/07/error-handling-and-go.html
>
> Concern 1: Isn't this just saving a few keystrokes?
>
> Allowing developers to pass back an array and then access the members
> of the array isn't the same thing, and we're not just saving a few
> keystrokes if this is implemented. Providing this ability promotes
> usage and clarity, and I'm confident Go would not have gotten
> developers to follow this convention if the syntax didn't facilitate
> the approach. I now write my Python code to handle errors in this same
> manner, taking advantage of its ability to handle comma-separated
> lists as tuples (something I didn't know about until recently, I must
> confess):
>
> http://stackoverflow.com/questions/423710/return-more-than-one-value-from-a-function-in-python
>
> Concern 2: Why don't you just use Python or Go?
>
> I really like using PHP for web development.
>
> Concern 3: Are you saying we should get rid of errors and exceptions?
>
> To be clear, errors have their place (maybe an extension failed to
> load, or a warning about usage of undeclared vars, etc.), and so do
> exceptions (for events that are truly "exceptional", that should cause
> a major revision to the branching/flow of the application and/or stop
> the application in its tracks if left unhandled.)
>
> Adam
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>

The problem with all of this is that the parser just isn't up to the task
of list comprehension. Be that as it may, that's not to say it can't ever
be done if someone wanted to take on the challenge of rewriting the parser
or providing an actual working implementation. The problem is you still
have a lot more challenges past just getting the list comprehension into
the engine. What you're talking about has many flaws just the same as the
existing error handling approach.

1) It depends on order of return values

2) It requires breaking BC in a way that will effect every single PHP user
out there.

3) It requires re-factoring virtually every PHP function, of which PHP has
thousands upon thousands.

4) It doesn't make error handling that much easier in PHP, because you
still have to check the error state regardless of how it's obtained.
Believe it or not passing back an array is the same thing. All you're
describing here is syntax sugar that allows the engine to do list
comprehension for you on the fly.


I agree that there needs to be a better approach to error handling in PHP.
I disagree that this is it or that it solves the problem any better than we
do today.

Reply via email to