I just saw Daniel changing some of the PEAR classes to use Exceptions,
and it's pretty clear that this could cause havoc with the end users.
The problem being that there is no 'soft' landing for the migration process.
Users switching code from return style error handling to exceptions are
not given any hints about what would be affected, and what may need fixing.
This is mainly due to the fact that Exceptions can occur anywhere inside
of multiple nested function calls, and failure to catch them is
frequently due to missing the fact that a dependent library of function
call could raise an exception.
So in looking at how this could be addressed, I thought I'd throw this
idea out there and see how it bounced..
PHP enforces rules like $this can not be used in a method marked
'static'. So why not flag methods (and internal functions) with a flag
that indicates they can throw things. Since PHP is not a compiled
language we can not pick up 'all' of the potential scenarios, but even
if E_NOTICE's pick up 80% it would make code considerably more maintainable.
So this is the rough outline..
Existing code that throws exception
1: function throwSomething() {
2: ...
3: throw new Exception
4: }
Would produce Compile-time warning: "E_NOTICE: throw used inside
non-catchable function on line 3"
The remove the warning:
1: catchable function throwSomething() {
2: ...
3: throw new Exception
4: }
Calling a function
1: function callThrow()
2: {
3: $this->throwSomething();
4: }
Would produce Run-time warning: "E_NOTICE catchable method called inside
non-catchable function or try/catch on line 3"
Fix:
either wrap the call in try/catch or make the function catchable.
Anyway... flame away ;)
Regards
Alan
PHP enforces rules like $this can not be used in a method marked 'static'.
So why not flag methods (and internal functions) with a flag that indicates
they can throw things. Since PHP is not a compiled language we can not pick
up 'all' of the potential scenarios, but even if E_NOTICE's pick up 80% it
would make code considerably more maintainable.
I don't like this. It's basically the equivalent of Java's "throws
Exception" antipattern[0] with none of the claimed benefits of
checked, fine grained exception specification (which I'm dubious about
in general, particularly having also used C++'s static exception
specifiers, which are even worse than Java's dynamic ones).
There are issues with both backward and forward compatibility here:
assuming this was in PHP 5.5, you could effectively no longer write
code that was E_STRICT/E_NOTICE clean in both PHP 5.4 and 5.5 — you
can't add catchable to functions in PHP 5.4 because it's not a
keyword, but you can't throw an exception in PHP 5.5 without it unless
you're prepared to incur a notice. And the associated performance
loss, which may turn out to be significant if it's happening on most
function calls in a script's lifetime.
Also, I already know how to use exceptions, and write clean code. I
don't really want to have to add catchable to all of the functions
I've written that may throw — or may call library functions that may
throw — when I upgrade to PHP 5.5. It's a lot of work, and given that
a lot of libraries now use exceptions, a lot of developers would end
up almost mechanically adding catchable to pretty much every function,
which loses any minimal code quality advantage that might exist.
Exception specifications in general don't feel very PHPish to me, but
that would be a different discussion. Catchable, as a limited form of
exception specification, feels even less useful than that.
Anyway... flame away ;)
Sorry, I guess I kind of did. It's nothing personal. :)
Adam
[0] http://today.java.net/article/2006/04/04/exception-handling-antipatterns#throwingException
Reply inline..
PHP enforces rules like $this can not be used in a method marked 'static'.
So why not flag methods (and internal functions) with a flag that indicates
they can throw things. Since PHP is not a compiled language we can not pick
up 'all' of the potential scenarios, but even if E_NOTICE's pick up 80% it
would make code considerably more maintainable.
I don't like this. It's basically the equivalent of Java's "throws
Exception" antipattern[0] with none of the claimed benefits of
checked, fine grained exception specification (which I'm dubious about
in general, particularly having also used C++'s static exception
specifiers, which are even worse than Java's dynamic ones).
Yes, it seems that anti-pattern document is actually the current
specification for PHP's exceptions design. Naming the exceptions that
could be thrown is probably not a bad idea, however as you say the
syntax change is a problem..
There are issues with both backward and forward compatibility here:
assuming this was in PHP 5.5, you could effectively no longer write
code that was E_STRICT/E_NOTICE clean in both PHP 5.4 and 5.5 — you
can't add catchable to functions in PHP 5.4 because it's not a
keyword, but you can't throw an exception in PHP 5.5 without it unless
you're prepared to incur a notice.
The other alternative would be to use docblocks, and testing for
"@throws ... \n" if a function throws an exception. This may mean that
this would be feasible as an extension, as it would not have modify the
parser syntax. and could be implemented on PHP 5.3 or less....
just like you would set error_reporting(E_ALL) at the start of the code,
you could add exception_reporting(E_ALL);
Also, I already know how to use exceptions, and write clean code.
All I will say to that is "So do I!" ;) however knowing how to, and
actually doing it are two different things (I'm a human who makes
mistakes, so I'd rather get all the help I can)
I
don't really want to have to add catchable to all of the functions
I've written that may throw — or may call library functions that may
throw — when I upgrade to PHP 5.5. It's a lot of work, and given that
a lot of libraries now use exceptions, a lot of developers would end
up almost mechanically adding catchable to pretty much every function,
which loses any minimal code quality advantage that might exist.
Which sounds like a extension using docblocks may be a good place for
this.. I just wonder how you can stop the behavior of all developers
just adding @throws Exception - unless you insist on it being a 'named'
exception other than the base one..
Exception specifications in general don't feel very PHPish to me, but
that would be a different discussion. Catchable, as a limited form of
exception specification, feels even less useful than that.
Not a great fan of them either, but if we to use them at least give me
some of the classic PHP tools (warnings) to make them less painfull..
Regards
Alan
Anyway... flame away ;)
Sorry, I guess I kind of did. It's nothing personal. :)Adam
[0] http://today.java.net/article/2006/04/04/exception-handling-antipatterns#throwingException
I just saw Daniel changing some of the PEAR classes to use Exceptions,
and it's pretty clear that this could cause havoc with the end users.
The problem being that there is no 'soft' landing for the migration
process.Users switching code from return style error handling to exceptions are
not given any hints about what would be affected, and what may need fixing.
Couldn't you just use a default exception handler via
set_exception_handler()
to implement a "soft landing" mechanism?
-Rasmus
response below...
I just saw Daniel changing some of the PEAR classes to use Exceptions,
and it's pretty clear that this could cause havoc with the end users.
The problem being that there is no 'soft' landing for the migration
process.Users switching code from return style error handling to exceptions are
not given any hints about what would be affected, and what may need fixing.
Couldn't you just use a default exception handler via
set_exception_handler()
to implement a "soft landing" mechanism?
This solves the problem of what happens when an exceptional event
happens, the system fails (logging something to the error log or
rendering an error). However does not really fix the consumer issue that
it expected a return value, not an exception.
However previously when a error occured, it was handed by the checking
of return value (eg. PEAR::isError()).. This means that all previous
code that checked for return values has to determine should it check for
exceptions (try/catch) or does the method still return a error value
This either means that you will have to one of the below.
a) have complete test suites to spot all these exceptional cases
b) do a full code review
c) wait until each exceptional event occurs, and fix when found..
This obviously is a problem with new code as well, using exceptions in
PHP is a good luck proposition, anything larger than a small script is
basically going to either wrap most of the code as try/catch or pray
that the developer has not forgotten that a particular call may throws
an exception (I doubt I would be able to do this, so I really do not
expect others to get this perfect as well).
Rather than this hap-hazard approach to ensuring code is correctly
handling error conditions would it not be far better for the engine to
be advising of situations where this may be occurring before they
occur.. in the same way undefined variables issue warnings. writing
code that throws exceptions should throw warnings if it's likely that it
is not handled.
Alan
-Rasmus
Rather than this hap-hazard approach to ensuring code is correctly
handling error conditions would it not be far better for the engine to
be advising of situations where this may be occurring before they
occur.. in the same way undefined variables issue warnings. writing
code that throws exceptions should throw warnings if it's likely that it
is not handled.
Well, I don't disagree with you. This is why we don't throw exceptions
from the core of PHP. But I don't see how the engine can warn you about
this case in any sort of compatible way that isn't likely to drive
people crazy with warnings on perfectly valid code.
-Rasmus
I just saw Daniel changing some of the PEAR classes to use Exceptions,
and it's pretty clear that this could cause havoc with the end users.
The problem being that there is no 'soft' landing for the migration
process.
If I understand set_exception_handler correctly, you could simply make
anything that reaches that state simply not return at all, and exit.
If you are that serious about the problem, the code expecting a result
and not an exception won't get anything at all.
And code with proper exception handling will do the right thing,
assuming you have written all your exception handlers at every layer
correctly.
Personally, try/catch and throw always felt like "GOTO" to me, and the
larger the codebase, the harder I found it to track down who was the
thrower and who was the catcher.
Reminded me of the old Abbot and Costello baseball routine.
--
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FS9NLTNEEKWBE