As a matter of consistency, I would like to suggest that for those
extensions which have a OO/procedural syntax that the non-fatal errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax. I have already committed such a change to Tidy, and I
can't see any serious reason why such a change can't be implemented for
internal classes.
Feedback welcome.
John
--
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-
John Coggeshall http://www.coggeshall.org/
The PHP Developer's Handbook http://www.php-handbook.com/
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=
As a matter of consistency, I would like to suggest that for those
extensions which have a OO/procedural syntax that the non-fatal errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax. I have already committed such a change to Tidy, and I
can't see any serious reason why such a change can't be implemented for
internal classes.Feedback welcome.
I wholeheartedly support this. I've been trying to document exception
handling this week and it's extremely frustrating:
-
None (almost none?) of the internal classes use exceptions. This
makes it difficult (if not impossible) to explain how to use
exceptions because you cannot show a meaningful example. -
Point #1 is a lie because internal classes throw exceptions when
there's an error in the constructor. This is leads to wacky code:
try {
$db = new SQLiteDatabase('foo.db');
if ($db->query($sql)) {
// fetch rows
} else {
// handle error
}
} catch {
// handle exception
}
It's really crazy to need to mix both types of error handling within
the same block of code.
-
Because internal classes don't use exceptions, I have no idea how
anyone can meaningfully use exceptions in their code. Even if all
userspace errors throw exceptions, people will miss lots of other
errors (i.e the ones from internal classes) unless they explicitly
check for them themselves and manually throw exceptions.Needing to turn errors into exceptions, however, seems to
completely defeat one of the primary points of exception handling,
which is separating core programming logic from error handling.
I wish I had to foresight to realize this earlier, but it didn't
emerge until I began to use PHP 5 in a more comprehensive way.
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
- None (almost none?) of the internal classes use exceptions. This
makes it difficult (if not impossible) to explain how to use
exceptions because you cannot show a meaningful example.
As of today, Tidy throws Exceptions in a object context.
It's really crazy to need to mix both types of error handling within
the same block of code.
Completely agree
--
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-
John Coggeshall http://www.coggeshall.org/
The PHP Developer's Handbook http://www.php-handbook.com/
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=
Note that sqlite does have an option to raise exceptions instead of errors.
I haven't tried this myself; Marcus will be able to advise more on how this
works.
--Wez.
try {
$db = new SQLiteDatabase('foo.db');
if ($db->query($sql)) {
// fetch rows
} else {
// handle error
}
} catch {
// handle exception
}It's really crazy to need to mix both types of error handling within
the same block of code.
Hello Wez,
SQLite only throws exceptions from constructors. This is necessary to get
the "constructor failed" information. It works using the support functions
from main/main.c/main/php.h:
typedef enum {
EH_NORMAL = 0,
EH_SUPPRESS,
EH_THROW
} error_handling_t;
PHPAPI void php_set_error_handling(error_handling_t error_handling, zend_class_entry *exception_class TSRMLS_DC);
#define php_std_error_handling() php_set_error_handling(EH_NORMAL, NULL
TSRMLS_CC)
php_set_error_handling(() sets the mode and class_entry.
php_std_error_handling() resets the mode and class entry.
EH_NORMAL => Standard behavior = no exceptions
EH_SUPPRESS => Neither throw an exception nor show/log the error
EH_THROW => Throw an exception if no excpetion is pending
If exception_class == NULL
then a standard exception will be
generated.
Monday, April 12, 2004, 11:31:46 PM, you wrote:
Note that sqlite does have an option to raise exceptions instead of errors.
I haven't tried this myself; Marcus will be able to advise more on how this
works.
--Wez.
try {
$db = new SQLiteDatabase('foo.db');
if ($db->query($sql)) {
// fetch rows
} else {
// handle error
}
} catch {
// handle exception
}It's really crazy to need to mix both types of error handling within
the same block of code.
--
Best regards,
Marcus mailto:helly@php.net
As a matter of consistency, I would like to suggest that for those
extensions which have a OO/procedural syntax that the non-fatal errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax. I have already committed such a change to Tidy, and I
can't see any serious reason why such a change can't be implemented for
internal classes.Feedback welcome.
I think it's a stupid idea (actually OO is a stupid idea but that's
something for another dicussion ;-):
-
In order to silently ignore failed queries you still have to put a
stupid try..except block around it. -
KISS: PHP is supposed to be SIMPLE; with all thos advanced OO stuff
writing scripts for PHP starts becoming less and less easy. Sure,
they are already using OO but that's just a notation. Some extensions
are only OO, like DOM, but that doesn't mean that every Joe Average
has any idea on what exceptions are. Please, kepe things simple.
Don't force people.
Derick
Derick Rethans wrote:
I think it's a stupid idea (actually OO is a stupid idea but that's
something for another dicussion ;-):
- In order to silently ignore failed queries you still have to put a
stupid try..except block around it.
If it's used only in object context.
- KISS: PHP is supposed to be SIMPLE; with all thos advanced OO stuff
writing scripts for PHP starts becoming less and less easy. Sure,
they are already using OO but that's just a notation. Some extensions
are only OO, like DOM, but that doesn't mean that every Joe Average
has any idea on what exceptions are. Please, kepe things simple.
Don't force people.
Supposed to be simple but oriented a little bit to the enterprise, otherwise why do we
have a ext/soap? An while for the Joe Average a failed query is just nothing for an
application which not fault tolerant this is something different. Joe Average even does
not need to use OO interface for simple scripts, while serious application goes OO (except
FUDForum ;) but Ilia wanted speeed). So, I don't find any problems of internal classes
throwing exceptions in object context. This was something I though is gonna be implemented
by the engine which can realize on compile time whether OO is used or not and
php_error_docref() to work just like now for procedural code and throw exceptions for OO
code (which can break some existing code of course). AFAIR Andi or Zeev explained that's
not possible or won't be implemented.
Finally, it looks that RC2 won't be released anytime soon and this issue can be fixed in
the meantime.
Andrey
On Mon, 12 Apr 2004 13:02:19 +0200
php@hristov.com (Andrey Hristov) wrote:
Derick Rethans wrote:
I think it's a stupid idea (actually OO is a stupid idea but
that's something for another dicussion ;-):
- In order to silently ignore failed queries you still have to
put a
stupid try..except block around it.
If it's used only in object context.
And why OO codes should be overbloated with exceptions for non fatal
errors? I do not talk about fatal userland errors but fatal php
erros. But I may be a too old fashion programmer, where exceptions
were used to avoid crash, ugly exit and but not control flow.
I feel these exceptions issues more like the other "OO fanatic"
discussions. It will fall in many annoyed things in our codes,
depending about how the maintainers use exceptions. For instance
(I took tidy codes, no offence for the authors, I like tidy, but
not its exceptions usage):
if (tidyOptIsReadOnly(opt)) {
TIDY_THROW("Attempt to set read-only option '%s'", optname);
return FAILURE;
}
Ah? Sounds more like a notice to me. This kills the KISS.
My nightmare (shows the E_ERROR/E_WARNING issues explained in other
posts):
./sapi/cli/php -n -r 'tidy_parse_file("foo");echo "bar";'
The worst is:
tidy_get_opt (internal function name) which raises an exception if
the option does not exist. What a nightmare if I have to try{}catch
every piece of codes because the KISS'ed value/false principle is
droped in the name of OO.
So yes, a little HOWTO for the usage of exceptions should be nice,
both for internals and userland. But if the goals is to follow these
examples, then I ask to add an ini option: use_crappy_exceptions
On|Off
my little 2cts on this topic,
pierre
At 12:41 PM 4/12/2004 +0200, Derick Rethans wrote:
As a matter of consistency, I would like to suggest that for those
extensions which have a OO/procedural syntax that the non-fatal errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax. I have already committed such a change to Tidy, and I
can't see any serious reason why such a change can't be implemented for
internal classes.Feedback welcome.
I think it's a stupid idea (actually OO is a stupid idea but that's
something for another dicussion ;-):
In order to silently ignore failed queries you still have to put a
stupid try..except block around it.KISS: PHP is supposed to be SIMPLE; with all thos advanced OO stuff
writing scripts for PHP starts becoming less and less easy. Sure,
they are already using OO but that's just a notation. Some extensions
are only OO, like DOM, but that doesn't mean that every Joe Average
has any idea on what exceptions are. Please, kepe things simple.
Don't force people.
Derick,
The fact that you have something personal against OOP doesn't mean it's not
good.
I think that functional context should continue to work as usual, but
there's a big advantage to be able to catch problems with try/catch and not
have to if() each internal function call separately (which you probably
don't do :)
I don't see a problem with OOP extensions throwing exceptions.
Andi
I don't see a problem with OOP extensions throwing exceptions.
Andi
There is 1 problem with this approach. Currently an uncaught exceptions
results in a fatal error (E_ERROR) meaning that if a particular method throws
an exceptions it MUST be caught otherwise the script will terminate. Having
to wrap some methods inside exceptions can be extremely frustrating since you
may want to allow those methods to fail. For example the query method in
SQLite can safely be allowed to fail in certain instances. In other instances
when you care about failures there may be a need to implement custom handlers
depending on the nature of the error. For example if a query fails due to a
uniqness constrait, an UPDATE query would be ran while in all other instances
an error would be logged etc...
Ilia
There is 1 problem with this approach. Currently an uncaught exceptions
results in a fatal error (E_ERROR) meaning that if a particular method throws
an exceptions it MUST be caught otherwise the script will terminate. Having
to wrap some methods inside exceptions can be extremely frustrating since you
may want to allow those methods to fail.
Yes. This sucks. Maybe PHP should only issue exceptions for problems
of E_WARNING
severity. An exception is an "Exceptional Event." If you
have an E_NOTICE
or E_STRICT
then that's an informational event, not a
exceptional one.
Either that or uncaught exceptions should be E_WARNINGs instead of
E_ERRORs. (I don't want to introduce Java's checked versus unchecked
exception concept.)
For example the query method in SQLite can safely be allowed to fail
in certain instances. In other instances when you care about
failures there may be a need to implement custom handlers depending
on the nature of the error. For example if a query fails due to a
uniqness constrait, an UPDATE query would be ran while in all other
instances an error would be logged etc...
Still, you shouldn't be ignoring E_WARNINGs unless you have a good
reason. Your code cannot correctly retrieve those rows from the
database when you've ignored the error telling you that there was a
problem connecting to the database. :)
Handling UNIQUEness queries is exactly the type of problem you're
going to need to trap. For example:
try {
$db = new SQLiteDatabase('foo.db');
$db->query('INSERT...');
} catch (SQLiteException $e) {
if ($e->getCode() == 19) {
// UNIQUEness violation
$db->query('UPDATE...');
} else {
// log error
error_log($e->getMessage() . ': ' . $e->getCode());
}
}
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
There is 1 problem with this approach. Currently an uncaught
exceptions
results in a fatal error (E_ERROR) meaning that if a particular
method throws
an exceptions it MUST be caught otherwise the script will terminate.
Having
to wrap some methods inside exceptions can be extremely frustrating
since you
may want to allow those methods to fail.Yes. This sucks. Maybe PHP should only issue exceptions for problems
ofE_WARNING
severity. An exception is an "Exceptional Event." If you
have anE_NOTICE
orE_STRICT
then that's an informational event, not a
exceptional one.
I'm fine with this, but it's really just a documentation problem,
right? Your method can still fail, you just need to try/catch around
it.
try {
$obj->bornToFail();
}
catch(Exception $e){}
Uglier than just swallowing a warning for sure, but still just a doc
problem.
Either that or uncaught exceptions should be E_WARNINGs instead of
E_ERRORs. (I don't want to introduce Java's checked versus unchecked
exception concept.)
-1.
George
There is 1 problem with this approach. Currently an uncaught
exceptions
results in a fatal error (E_ERROR) meaning that if a particular
method throws
an exceptions it MUST be caught otherwise the script will terminate.
Having
to wrap some methods inside exceptions can be extremely frustrating
since you
may want to allow those methods to fail.Yes. This sucks. Maybe PHP should only issue exceptions for problems
ofE_WARNING
severity. An exception is an "Exceptional Event." If you
have anE_NOTICE
orE_STRICT
then that's an informational event, not a
exceptional one.I'm fine with this, but it's really just a documentation problem,
right? Your method can still fail, you just need to try/catch around
it.try {
$obj->bornToFail();
}
catch(Exception $e){}Uglier than just swallowing a warning for sure, but still just a doc
problem.
Might there be a possibility that an exception inside a "@ context" could
be ignored, too (that might also work with active custom error handlers,
I guess)?
Cheers,
Michael
Still, you shouldn't be ignoring E_WARNINGs unless you have a good
reason.
There are plenty of situations where E_WARNING
can be safely ignored. And even
more situations where E_NOTICE/E_STRICT can be ignored.
Your code cannot correctly retrieve those rows from the
database when you've ignored the error telling you that there was a
problem connecting to the database. :)
You may not want to retrieve the rows in the 1st place.
Handling UNIQUEness queries is exactly the type of problem you're
going to need to trap. For example:
Your example is not entirely correct. You'd first need to use
$db->lastError() to the error code, $e->getCode() will return something else
all together. However the bottom line is that now your exception handling
mechanism is far more complex then it should/could be. If your block has a
query() method with a query that can fail you'd need to add special
conditions to handle it in the end you end up with an overly complex handling
mechanism.
If you start putting an try {} catch {} block around every individual query
method as an alternative, then you kill the whole point of exceptions, no?
Ilia
Still, you shouldn't be ignoring E_WARNINGs unless you have a good
reason.There are plenty of situations where
E_WARNING
can be safely ignored. And even
more situations where E_NOTICE/E_STRICT can be ignored.
Well, like I said, I'm against exceptions on E_NOTICE/E_STRICT. I
think there's some agreement on this point. Well, you, me, George, and
Derick. I add Derick because he's always against exceptions. :)
As to E_WARNINGs, what to do? Sometimes they can be safely ignored,
but it takes an experienced programmer to know those cases.
Your code cannot correctly retrieve those rows from the
database when you've ignored the error telling you that there was a
problem connecting to the database. :)You may not want to retrieve the rows in the 1st place.
So you're saying you write code like:
// Don't care if this prints anything:
$db = new SQLiteDatabase('foo.db');
$r = $db->query($sql);
foreach ($r as $row) {
processRow($row);
}
I think only two sets of programmers do this. Unfortunately, they're
at the spectrums. Newbies and gurus. Newbies because they don't know
any better and gurus because they know exactly what's going to happen.
I'm trying to get newbies to move into the middle range and I'm
ignoring the top 1% of developers. :)
Handling UNIQUEness queries is exactly the type of problem you're
going to need to trap. For example:Your example is not entirely correct. You'd first need to use
$db->lastError() to the error code, $e->getCode() will return something else
all together. However the bottom line is that now your exception handling
mechanism is far more complex then it should/could be. If your block has a
query() method with a query that can fail you'd need to add special
conditions to handle it in the end you end up with an overly complex handling
mechanism.
Right. Sorry about that. I had played around with trying to get SQLite to
throw exceptions and had placed the lastError() as the exception code.
If you start putting an try {} catch {} block around every individual query
method as an alternative, then you kill the whole point of exceptions, no?
FWIW, I just checked, and Java handles this dilemma in JDBC by not
throwing exceptions upon SQL warnings. They still throw SQLExceptions
for major DB errors.
I am willing to concede that SQL parse errors aren't the best example
here, but that doesn't mean extensions should never throw exceptions.
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
As to E_WARNINGs, what to do? Sometimes they can be safely ignored,
but it takes an experienced programmer to know those cases.
Perhaps, but if you limit the experienced programmer's options and/or make
using more advanced capabilities of the language more difficult you will lose
those programmers to other languages. Consequently these programmers are
usually the ones responsible for large deployments of the language.
So you're saying you write code like:
// Don't care if this prints anything:
$db = new SQLiteDatabase('foo.db');
$r = $db->query($sql);
foreach ($r as $row) {
processRow($row);
}
Almost ;-)
$r = $db->query($sql) or sql_error_handler($sql, $db);
It'll be the job of sql_error_handler() to determine what type of an error had
occurred and what action to take if any.
FWIW, I just checked, and Java handles this dilemma in JDBC by not
throwing exceptions upon SQL warnings. They still throw SQLExceptions
for major DB errors.
Well, that would mean that you'll never be certain what may throw an
exceptions giving you a nasty mix of both that will confuse experienced and
inexperienced developers alike.
Ilia
Adam Maccabee Trachtenberg wrote:
I am willing to concede that SQL parse errors aren't the best example
here, but that doesn't mean extensions should never throw exceptions.
If a user has written code expecting it to work in PHP 4 and PHP 5 with
a registered error handler, it has to be completely rewritten.
Exceptions, by nature, can not be caught at the global level and then
modified, they are local. Of course, you could just surround your
global code with a try {} catch {} but that is just about the worst hack
I can imagine.
Unless there is a way to "resume" execution after the point of the error
(i.e. exactly how the current error handling works), exceptions will
only make things more exasperating. If I have to surround every single
method call with try {} catch {}, that = a bad design decision.
- say byebye to readability
- what if an extension upgrades and throws a new, more specific kind of
exception? instant code breakage, unless the catch-all is not paranoid - EVERY try {} catch {} will need a catch-all, unless you're willing to
risk total breakage later. - error handling is suddenly forced to be directly integrated with
program logic, and isn't that the opposite of exception handling's goals?
Greg
P.S.
This is what I mean by a "resume" statement:
function blah()
{
$a = $someobject->throwsexception();
$nextstatement = 'works?';
}
...
try {
blah();
} catch (Exception $e) {
log_exception($e);
if (thingsareok()) {
resume; // execution starts at "$nextstatement = 'works?';"
}
}
Without the ability to resume, we are forced to do
function blah()
{
try {
$a = $someobject->throwsexception();
} catch (Exception $e) {
$ok = pass_to_global_exception_handler_and_logger($e);
if (!$ok) {
throw ($e);
}
}
$nextstatement = 'ack';
}
for even the most minor of error conditions
Adam Maccabee Trachtenberg wrote:
I am willing to concede that SQL parse errors aren't the best example
here, but that doesn't mean extensions should never throw exceptions.If a user has written code expecting it to work in PHP 4 and PHP 5 with
a registered error handler, it has to be completely rewritten.
If you're expecting this code to work in both PHP 4 and PHP 5, you're
not using the OO extension interface, so no exceptions will be
thrown. Things will work just like before.
I also presume that exceptions are not handled by a registed error
handler. That would be madness. :)
I think by now I am resigned to the situation that PHP's internal
error reporting system doesn't doesn't map well to exception
handling.
This problem is at least somewhat related to inconsistent application
of E_WARNINGs, E_ERRORs, etc. Certain extensions (SOAP, Ming) love to
throw E_ERRORs. Others won't throw an E_ERROR
in even the worst of
circumstances. Therefore, sometimes E_WARNINGs are harmless and other
times they're fatal.
Oh well.
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
I think that functional context should continue to work as usual, but
there's a big advantage to be able to catch problems with try/catch and not
have to if() each internal function call separately (which you probably
don't do :)
I don't see a problem with OOP extensions throwing exceptions.
I agree. I don't think we should modify the functional context at
all.
However, uf bundled extensions don't throw exceptions (or even worse,
some do and some don't) then why did we both implementing exceptions?
How can anyone rationally design an application when half of their
problems issue errors and the other half throw exceptions? That's a
recipe for disaster.
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
How can anyone rationally design an application when half of their
problems issue errors and the other half throw exceptions? That's a
recipe for disaster.
Exactly the reason why nothing should throw exceptions at all.
Derick
How can anyone rationally design an application when half of their
problems issue errors and the other half throw exceptions? That's a
recipe for disaster.Exactly the reason why nothing should throw exceptions at all.
If nothing should throw exceptions then they shouldn't be in the
language. However, having decided to place exceptions to the language,
it's only rational to implement them in a sane way.
I understand you're against them. Personally, I may not use
them. However, I really don't think it makes any sense to set
exceptions up for failure with a half-baked implementation.
(I'm not saying the ZE2 part of exeptions is half-baked. That
works. It's the deployment of exceptions that's half-baked.)
-adam
--
adam@trachtenberg.com
author of o'reilly's php cookbook
avoid the holiday rush, buy your copy today!
At 12:41 PM 4/12/2004 +0200, Derick Rethans wrote:
As a matter of consistency, I would like to suggest that for those
extensions which have a OO/procedural syntax that the non-fatal
errors
generated by those extensions be thrown as Exceptions when called
from
an OO syntax. I have already committed such a change to Tidy, and I
can't see any serious reason why such a change can't be implemented
for
internal classes.Feedback welcome.
I think it's a stupid idea (actually OO is a stupid idea but that's
something for another dicussion ;-):
In order to silently ignore failed queries you still have to put a
stupid try..except block around it.KISS: PHP is supposed to be SIMPLE; with all thos advanced OO stuff
writing scripts for PHP starts becoming less and less easy. Sure,
they are already using OO but that's just a notation. Some
extensions
are only OO, like DOM, but that doesn't mean that every Joe Average
has any idea on what exceptions are. Please, kepe things simple.
Don't force people.Derick,
The fact that you have something personal against OOP doesn't mean
it's not good.
I think that functional context should continue to work as usual, but
there's a big advantage to be able to catch problems with try/catch
and not have to if() each internal function call separately (which you
probably don't do :)
I don't see a problem with OOP extensions throwing exceptions.
I like OO (*), and I think warnings (non-fatal errors) as exceptions
are a stupid idea. Does that count? ;-)
Exceptions in languages like Java are used explicitly to catch fatal
errors, not to catch basic errors. Converting warnings to exceptions
would change the meaning of a warning from something which is nice for
development, or logging purposes, but handled by your control flow,
into an unrecoverable error.
Errors as exceptions are a different story. I don't think that's a bad
idea at all. But leave good alone, warnings shouldn't be exceptions.
-Sterling
(*) Though my like is most definitely due to stockholm syndrome, and
excessive brainrape. Nonetheless. :)
I like OO (*), and I think warnings (non-fatal errors) as exceptions
are a stupid idea. Does that count? ;-)Exceptions in languages like Java are used explicitly to catch fatal
errors, not to catch basic errors.
If 'languages like Java' means languages designed for OO, then this is
not true. Python throws exceptions for almost everything (KeyError,
for example). Even Java throws exceptions (java.sql.Exception) for
things like failed database connections which are warnings in PHP.
George
I like OO (*), and I think warnings (non-fatal errors) as exceptions
are a stupid idea. Does that count? ;-)Exceptions in languages like Java are used explicitly to catch fatal
errors, not to catch basic errors.If 'languages like Java' means languages designed for OO, then this is
not true. Python throws exceptions for almost everything (KeyError,
for example). Even Java throws exceptions (java.sql.Exception) for
things like failed database connections which are warnings in PHP.
Languages like Java doesn't mean languages designed for OO, but
languages closely adhering to the OO model that PHP uses, Java being
the language that can most easily be called the parent of our current
model - although I do keep Python in this context even after your
KeyError example. The triviality of an exception doesn't make
exceptions themselves less severe. Whether or not a KeyError is
warranted as an E_ERROR, doesn't in fact change that a KeyError will
bump you firmly out of your control flow branch, and make you handle an
error condition. In PHP, E_WARNINGs may be misused (that's a
discussion for another time, i think); but the fact remains, they do
not end your current control flow branch. Changing E_WARNING's to
errors catchable by try{}catch{} will not only break BC, but will not
make sense for a large number of warnings currently thrown for PHP and
lead to the same inconsistencies.
John has gone ahead and committed a perfect example of where exceptions
just mess things up. In the tidy extension if you try and set an
unknown configuration option it throws an exception. This is not by
any stretch of the imagination an unrecoverable error, but rather a
simple failure. Yet, if you use tidy in a script, and it is not within
a try {} catch {} block your script execution will be terminated
because the configuration option could not be resolved. This is much
less than desirable and probably confusing for someone who doesn't
understand what an exception or why he should care.
You might argue that python or java would throw an exception in this
case. For the majority of the java standard library and python code i
have found this the opposite, however, even conceding that, PHP should
never do this. We have the concept of warnings, in our world an error
of this type does not terminate script execution. There are even
less severe usages of warnings throughout the PHP source code, and
there is no reason to convert them to exceptions. And if you don't,
you still have the same inconsistencies.
Java and Python both use a mix of philosophies, and indeed there is no
complete consensus. However, in my experience and the books that I've
read on the subject, the general thought is:
a) throw specific exceptions, not just a "tidy_exception." PHP would
need to add a library of built-in exceptions to make this even remotely
useful. this is not feasible to do at RC1.66666667
b) don't throw exceptions except when truly exceptional. a function
failing is usually not an exception, but rather signified by failure.
The exception to this is when using constructors that contain logic
(considered bad practice by many btw), and overloading. In these cases
exceptions are used in leu of a better solution. This brings us back
to KeyError - KeyError is only thrown when overloading is used:
names = ["barney", "fred", "wilma"]
print names["betty"] # throws an exception
print names.get("betty") # returns None
Most of the exceptions i've found when using both these languages
happen on something that maps to something more severe than a
configuration option not being found. YMMV.
-Sterling
not end your current control flow branch. Changing E_WARNING's to
errors catchable by try{}catch{} will not only break BC, but will not
make sense for a large number of warnings currently thrown for PHP and
lead to the same inconsistencies.
There is no BC break here. We are talking about specifically new
extensions written against ZE2 which have error conditions that should
be recoverable -- and only in the object context. Since most of PHP
does not provide a object context, there is no expectation that they
should be modified for exceptions.
John has gone ahead and committed a perfect example of where exceptions
just mess things up. In the tidy extension if you try and set an
unknown configuration option it throws an exception. This is not by
any stretch of the imagination an unrecoverable error, but rather a
simple failure. Yet, if you use tidy in a script, and it is not within
a try {} catch {} block your script execution will be terminated
because the configuration option could not be resolved. This is much
less than desirable and probably confusing for someone who doesn't
understand what an exception or why he should care.
You have pulled one edge case out of an entire API, and the problem here
is probably that you shouldn't complain about setting an invalid
configuration option at all -- perhaps as a E_NOTICE. Furthermore, this
exception will only occur if you use $a = new tidy() instead of $a =
tidy_parse_file().
You might argue that python or java would throw an exception in this
case. For the majority of the java standard library and python code i
have found this the opposite, however, even conceding that, PHP should
never do this. We have the concept of warnings, in our world an error
of this type does not terminate script execution. There are even
less severe usages of warnings throughout the PHP source code, and
there is no reason to convert them to exceptions. And if you don't,
you still have the same inconsistencies.
Again, we are talking about a very specific situation (PHP 5 extensions
written using a dual-syntax model).Things in the PHP 4 branch are not an
issue here, there is no expectation that such things would be changed.
a) throw specific exceptions, not just a "tidy_exception." PHP would
need to add a library of built-in exceptions to make this even remotely
useful. this is not feasible to do at RC1.66666667
Agreed. You can't do this in the time allowed. However, you can make
things throw tidy_exception and then in PHP 5.1 throw
tidySomeOtherMoreSpecificException which extends tidy_exception.
b) don't throw exceptions except when truly exceptional. a function
failing is usually not an exception, but rather signified by failure.
The exception to this is when using constructors that contain logic
(considered bad practice by many btw), and overloading. In these cases
exceptions are used in leu of a better solution. This brings us back
to KeyError - KeyError is only thrown when overloading is used:
If you're argument is that there should be some sort of consistency on
when an error is really an exception, I can't agree more.. However, that
it itself is an admission that there is a place for Exceptions in
internal PHP 5 OO which is not being addressed.
Most of the exceptions i've found when using both these languages
happen on something that maps to something more severe than a
configuration option not being found. YMMV.
Its a two-line change that I'm willing to make -- I'm more concerned
about the other extensions which are not using exceptions at all,
especially when they are warranted.
John
--
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=-
John Coggeshall http://www.coggeshall.org/
The PHP Developer's Handbook http://www.php-handbook.com/
-=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=--=~=
On Mon, 12 Apr 2004 13:18:51 -0400
john@coggeshall.org (John Coggeshall) wrote:
We may keep in mind that a specific (or rare) situations now will
certainly be a not so rare situation in a near future. When PHP5 is
out and people start to create php5 only extensions (thinking that
the internal API will then really be freezed).
pierre
On Mon, 12 Apr 2004 13:18:51 -0400
<snip> > Again, we are talking about a very specific situation (PHP 5 > extensions written using a dual-syntax model).Things in the PHP 4 > branch are not an issue here, there is no expectation that such > things would be changed.
john@coggeshall.org (John Coggeshall) wrote:We may keep in mind that a specific (or rare) situations now will
certainly be a not so rare situation in a near future. When PHP5 is
out and people start to create php5 only extensions (thinking that
the internal API will then really be freezed).
That's why this discussion is happening now.
George
I like OO (*), and I think warnings (non-fatal errors) as exceptions
are a stupid idea. Does that count? ;-)Exceptions in languages like Java are used explicitly to catch fatal
errors, not to catch basic errors.If 'languages like Java' means languages designed for OO, then this
is not true. Python throws exceptions for almost everything
(KeyError, for example). Even Java throws exceptions
(java.sql.Exception) for things like failed database connections
which are warnings in PHP.Languages like Java doesn't mean languages designed for OO, but
languages closely adhering to the OO model that PHP uses, Java being
the language that can most easily be called the parent of our current
model - although I do keep Python in this context even after your
KeyError example. The triviality of an exception doesn't make
exceptions themselves less severe. Whether or not a KeyError is
warranted as an E_ERROR, doesn't in fact change that a KeyError will
bump you firmly out of your control flow branch, and make you handle
an error condition. In PHP, E_WARNINGs may be misused (that's a
discussion for another time, i think); but the fact remains, they do
not end your current control flow branch. Changing E_WARNING's to
errors catchable by try{}catch{} will not only break BC, but will not
make sense for a large number of warnings currently thrown for PHP and
lead to the same inconsistencies.
A KeyError is an E_NOTICE
in PHP. It's so frequent in loosely typed
languages that it is rarely severe. Your argument is a tautology: the
only reason it breaks control-flow in Python is because it's defined
to break control-flow there by means of it being an exception.
John has gone ahead and committed a perfect example of where
exceptions just mess things up. In the tidy extension if you try and
set an unknown configuration option it throws an exception. This is
not by any stretch of the imagination an unrecoverable error, but
rather a simple failure. Yet, if you use tidy in a script, and it is
not within a try {} catch {} block your script execution will be
terminated because the configuration option could not be resolved.
This is much less than desirable and probably confusing for someone
who doesn't understand what an exception or why he should care.
I don't have a strong feeling about this either way, but to play devils
advocate: You requested an option be set. That option could not be set
because it is impossible to set a non-existent option. How do you know
how someone wants to handle that error?
You might argue that python or java would throw an exception in this
case. For the majority of the java standard library and python code i
have found this the opposite, however, even conceding that, PHP should
never do this. We have the concept of warnings, in our world an error
of this type does not terminate script execution. There are even
less severe usages of warnings throughout the PHP source code, and
there is no reason to convert them to exceptions. And if you don't,
you still have the same inconsistencies.
The discussion was on OO code throwing exceptions. Given that there is
very little OO core code in php4, I don't see a widespread conversion
happening.
Java and Python both use a mix of philosophies, and indeed there is no
complete consensus. However, in my experience and the books that I've
read on the subject, the general thought is:a) throw specific exceptions, not just a "tidy_exception." PHP would
need to add a library of built-in exceptions to make this even
remotely useful. this is not feasible to do at RC1.66666667
But the beauty of OO Code is that all the tidy exceptions should derive
from TidyException. So life can continue as before, with no BC break.
b) don't throw exceptions except when truly exceptional. a function
failing is usually not an exception, but rather signified by failure.
The exception to this is when using constructors that contain logic
(considered bad practice by many btw), and overloading. In these
cases exceptions are used in leu of a better solution. This brings us
back to KeyError - KeyError is only thrown when overloading is used:names = ["barney", "fred", "wilma"]
print names["betty"] # throws an exception
print names.get("betty") # returns None
You'll have a hard time defending Python as being restrained in it's
use of exceptions for warnings. It's a rather exception-happy langugae
and throws exceptions for the equivalent of most PHP E_NOTICEs.
Most of the exceptions i've found when using both these languages
happen on something that maps to something more severe than a
configuration option not being found. YMMV.
The key point that you're missing in all this is that you don't know
what's a serious error and what's not. Only the developer knows. For
instance, the python smtplib can throw any number of exceptions based
on bad connect data or bad command responses. Is this a 'serious'
error? It depends. If sending a mail is an inconsequential part of
the app, maybe it's just an informational warning. It's also easy to
imagine it being a very critical, non-recoverable error. The severity
of the error lies entirely in the purview of the receiver.
Nothing sums this up for me better than KeyError, which is almost never
fatal in my applications but which constantly bites me in the ass.
Obviously your experiences may differ, which is really the whole point.
George
John has gone ahead and committed a perfect example of where
exceptions just mess things up. In the tidy extension if you try and
set an unknown configuration option it throws an exception. This is
not by any stretch of the imagination an unrecoverable error, but
rather a simple failure. Yet, if you use tidy in a script, and it is
not within a try {} catch {} block your script execution will be
terminated because the configuration option could not be resolved.
This is much less than desirable and probably confusing for someone
who doesn't understand what an exception or why he should care.I don't have a strong feeling about this either way, but to play
devils advocate: You requested an option be set. That option could
not be set because it is impossible to set a non-existent option. How
do you know how someone wants to handle that error?
I assume they don't want their script to stop executing, their
transactions to be rolled back and a nasty error page shown :
"Uncaught exception, could not set tabsize to 2 spaces"
That could just be my crazy assumption though.
You might argue that python or java would throw an exception in this
case. For the majority of the java standard library and python code
i have found this the opposite, however, even conceding that, PHP
should never do this. We have the concept of warnings, in our world
an error of this type does not terminate script execution. There
are even less severe usages of warnings throughout the PHP source
code, and there is no reason to convert them to exceptions. And if
you don't, you still have the same inconsistencies.The discussion was on OO code throwing exceptions. Given that there
is very little OO core code in php4, I don't see a widespread
conversion happening.
No, this discussion was on having exceptions thrown instead of
E_WARNINGs inside OO code. I'm pointing out that the two paradigms
don't map, and in other languages for many of the common errors given
by E_WARNINGs (but not all) simply wouldn't propagate as Exceptions.
Many cases it would, but in order for this idea to work, it needs to
map for the most part, which it doesn't.
Java and Python both use a mix of philosophies, and indeed there is
no complete consensus. However, in my experience and the books that
I've read on the subject, the general thought is:a) throw specific exceptions, not just a "tidy_exception." PHP would
need to add a library of built-in exceptions to make this even
remotely useful. this is not feasible to do at RC1.66666667But the beauty of OO Code is that all the tidy exceptions should
derive from TidyException. So life can continue as before, with no BC
break.b) don't throw exceptions except when truly exceptional. a function
failing is usually not an exception, but rather signified by failure.
The exception to this is when using constructors that contain logic
(considered bad practice by many btw), and overloading. In these
cases exceptions are used in leu of a better solution. This brings
us back to KeyError - KeyError is only thrown when overloading is
used:names = ["barney", "fred", "wilma"]
print names["betty"] # throws an exception
print names.get("betty") # returns NoneYou'll have a hard time defending Python as being restrained in it's
use of exceptions for warnings. It's a rather exception-happy
langugae and throws exceptions for the equivalent of most PHP
E_NOTICEs.
I haven't noticed that, and I've written quite a bit python code. It
does throw exceptions, no argument, but it depends largely on what you
are doing. The above example you've given is a place where an
exception is not out of place (although I don't particularly like one
being thrown), because you are using an overload. Different paradigm
than PHP arrays imho.
Most of the exceptions i've found when using both these languages
happen on something that maps to something more severe than a
configuration option not being found. YMMV.The key point that you're missing in all this is that you don't know
what's a serious error and what's not. Only the developer knows. For
instance, the python smtplib can throw any number of exceptions based
on bad connect data or bad command responses. Is this a 'serious'
error? It depends. If sending a mail is an inconsequential part of
the app, maybe it's just an informational warning. It's also easy to
imagine it being a very critical, non-recoverable error. The severity
of the error lies entirely in the purview of the receiver.Nothing sums this up for me better than KeyError, which is almost
never fatal in my applications but which constantly bites me in the
ass. Obviously your experiences may differ, which is really the whole
point.
Well, you can use get() now and be happy. :)
I'm not saying that exceptions should never be used. But, John
suggested "As a matter of consistency, I would like to suggest that for
those extensions which have a OO/procedural syntax that the non-fatal
errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax."
Either i'm missing the point or we are agreeing this shouldn't be so.
-Sterling
John has gone ahead and committed a perfect example of where
exceptions just mess things up. In the tidy extension if you try
and set an unknown configuration option it throws an exception.
This is not by any stretch of the imagination an unrecoverable
error, but rather a simple failure. Yet, if you use tidy in a
script, and it is not within a try {} catch {} block your script
execution will be terminated because the configuration option could
not be resolved. This is much less than desirable and probably
confusing for someone who doesn't understand what an exception or
why he should care.I don't have a strong feeling about this either way, but to play
devils advocate: You requested an option be set. That option could
not be set because it is impossible to set a non-existent option.
How do you know how someone wants to handle that error?I assume they don't want their script to stop executing, their
transactions to be rolled back and a nasty error page shown :"Uncaught exception, could not set tabsize to 2 spaces"
That could just be my crazy assumption though.
It is. It's a hardocded portion of their app, and they made a mistake.
They may not care, but it's also possible that they do. Assuming that
they don't care enough to fix it seems equally crazy to me.
You might argue that python or java would throw an exception in this
case. For the majority of the java standard library and python code
i have found this the opposite, however, even conceding that, PHP
should never do this. We have the concept of warnings, in our world
an error of this type does not terminate script execution. There
are even less severe usages of warnings throughout the PHP source
code, and there is no reason to convert them to exceptions. And if
you don't, you still have the same inconsistencies.The discussion was on OO code throwing exceptions. Given that there
is very little OO core code in php4, I don't see a widespread
conversion happening.No, this discussion was on having exceptions thrown instead of
E_WARNINGs inside OO code.
Rewind to the beginning of the discussion, the scope is not as broad as
you claim.
I'm pointing out that the two paradigms don't map, and in other
languages for many of the common errors given by E_WARNINGs (but not
all) simply wouldn't propagate as Exceptions. Many cases it would,
but in order for this idea to work, it needs to map for the most part,
which it doesn't.
[snip]
You'll have a hard time defending Python as being restrained in it's
use of exceptions for warnings. It's a rather exception-happy
langugae and throws exceptions for the equivalent of most PHP
E_NOTICEs.I haven't noticed that, and I've written quite a bit python code. It
does throw exceptions, no argument, but it depends largely on what you
are doing. The above example you've given is a place where an
exception is not out of place (although I don't particularly like one
being thrown), because you are using an overload. Different paradigm
than PHP arrays imho.Most of the exceptions i've found when using both these languages
happen on something that maps to something more severe than a
configuration option not being found. YMMV.The key point that you're missing in all this is that you don't
know what's a serious error and what's not. Only the developer
knows. For instance, the python smtplib can throw any number of
exceptions based on bad connect data or bad command responses. Is
this a 'serious' error? It depends. If sending a mail is an
inconsequential part of the app, maybe it's just an informational
warning. It's also easy to imagine it being a very critical,
non-recoverable error. The severity of the error lies entirely in
the purview of the receiver.Nothing sums this up for me better than KeyError, which is almost
never fatal in my applications but which constantly bites me in the
ass. Obviously your experiences may differ, which is really the
whole point.Well, you can use get() now and be happy. :)
I could, I could also catch my exceptions. There are plenty of other
exceptions (casting errors, etc) that will irk me whenever I use
Python.
I'm not saying that exceptions should never be used. But, John
suggested "As a matter of consistency, I would like to suggest that
for those extensions which have a OO/procedural syntax that the
non-fatal errors
generated by those extensions be thrown as Exceptions when called from
an OO syntax."
I'm undecided on whether it's advisable to throw E_WARNINGs as
exceptions. I think that all but engine-consistency-affecting E_ERRORs
should be exceptions, but that's a different discussion.
Either i'm missing the point or we are agreeing this shouldn't be so.
You were saying that not doing this was consistent with other
languages. I was saying that it was not.
George
John has gone ahead and committed a perfect example of where
exceptions just mess things up. In the tidy extension if you try
and set an unknown configuration option it throws an exception.
This is not by any stretch of the imagination an unrecoverable
error, but rather a simple failure. Yet, if you use tidy in a
script, and it is not within a try {} catch {} block your script
execution will be terminated because the configuration option could
not be resolved. This is much less than desirable and probably
confusing for someone who doesn't understand what an exception or
why he should care.I don't have a strong feeling about this either way, but to play
devils advocate: You requested an option be set. That option could
not be set because it is impossible to set a non-existent option.
How do you know how someone wants to handle that error?I assume they don't want their script to stop executing, their
transactions to be rolled back and a nasty error page shown :"Uncaught exception, could not set tabsize to 2 spaces"
That could just be my crazy assumption though.
It is. It's a hardocded portion of their app, and they made a
mistake. They may not care, but it's also possible that they do.
Assuming that they don't care enough to fix it seems equally crazy to
me.
Could be a version mismatch with tidy, and a newer library. They
develop there code, the option exists, and then someone with an older
version of the library doesn't have that. Whether or not i have 4
spaces or 2 in my output is rather inconsequential. Now you deploy
somewhere else and this explodes somewhere within a function and bumps
the script out of a critical execution context and refuses to work.
You might argue that python or java would throw an exception in
this case. For the majority of the java standard library and
python code i have found this the opposite, however, even conceding
that, PHP should never do this. We have the concept of warnings,
in our world an error of this type does not terminate script
execution. There are even less severe usages of warnings
throughout the PHP source code, and there is no reason to convert
them to exceptions. And if you don't, you still have the same
inconsistencies.The discussion was on OO code throwing exceptions. Given that there
is very little OO core code in php4, I don't see a widespread
conversion happening.No, this discussion was on having exceptions thrown instead of
E_WARNINGs inside OO code.Rewind to the beginning of the discussion, the scope is not as broad
as you claim.
I did. fast-forward to the end of this message, that's exactly the
point john brought up.
The key point that you're missing in all this is that you don't
know what's a serious error and what's not. Only the developer
knows. For instance, the python smtplib can throw any number of
exceptions based on bad connect data or bad command responses. Is
this a 'serious' error? It depends. If sending a mail is an
inconsequential part of the app, maybe it's just an informational
warning. It's also easy to imagine it being a very critical,
non-recoverable error. The severity of the error lies entirely in
the purview of the receiver.Nothing sums this up for me better than KeyError, which is almost
never fatal in my applications but which constantly bites me in the
ass. Obviously your experiences may differ, which is really the
whole point.Well, you can use get() now and be happy. :)
I could, I could also catch my exceptions. There are plenty of other
exceptions (casting errors, etc) that will irk me whenever I use
Python.
I've probably written a considerably large amount of python and I
haven't run into this rampant exception problem you talk about. Could
also be the reason why I like Python more than you... ;) It makes
sense that overloads would cause exceptions, as it does with type
casting exceptions - remember, python is a strongly typed language,
that type schiznizzle is important to them.
I'm not saying that exceptions should never be used. But, John
suggested "As a matter of consistency, I would like to suggest that
for those extensions which have a OO/procedural syntax that the
non-fatal errors
generated by those extensions be thrown as Exceptions when called
from an OO syntax."I'm undecided on whether it's advisable to throw E_WARNINGs as
exceptions. I think that all but engine-consistency-affecting
E_ERRORs should be exceptions, but that's a different discussion.
I would probably agree with you on E_ERRORs.
Either i'm missing the point or we are agreeing this shouldn't be so.
You were saying that not doing this was consistent with other
languages. I was saying that it was not.
Ok, then we disagree. I think its entirely inconsistent because the
two systems don't map to each other, and you get plenty of cases where
the two simply don't map. John is talking about all E_WARNINGs in OO
code, and in the procedural variants, sending E_WARNINGs. The scope of
E_WARNING
is not in my opinion the same scope as an exception in any
language, and we may just have to agree to disagree.
-sterling
It is. It's a hardocded portion of their app, and they made a
mistake. They may not care, but it's also possible that they do.
Assuming that they don't care enough to fix it seems equally crazy to
me.Could be a version mismatch with tidy, and a newer library. They
develop there code, the option exists, and then someone with an older
version of the library doesn't have that. Whether or not i have 4
spaces or 2 in my output is rather inconsequential. Now you deploy
somewhere else and this explodes somewhere within a function and bumps
the script out of a critical execution context and refuses to work.
Setting an option has semantic meaning. Whitespace has no semantic
meaning in PHP. These are apples and oranges.
Rewind to the beginning of the discussion, the scope is not as broad
as you claim.I did. fast-forward to the end of this message, that's exactly the
point john brought up.
He's talking about all E_WARNINGs in an OO context, not in an OO
extension.
I could, I could also catch my exceptions. There are plenty of
other exceptions (casting errors, etc) that will irk me whenever I
use Python.I've probably written a considerably large amount of python and I
haven't run into this rampant exception problem you talk about. Could
also be the reason why I like Python more than you... ;) It makes
sense that overloads would cause exceptions, as it does with type
casting exceptions - remember, python is a strongly typed language,
that type schiznizzle is important to them.
I'm not arguing whether it's important to them. I'm arguing that
things that are not important to my app generate exceptions in Python.
Something can be important in a language but not important to my app.
Either i'm missing the point or we are agreeing this shouldn't be so.
You were saying that not doing this was consistent with other
languages. I was saying that it was not.Ok, then we disagree. I think its entirely inconsistent because the
two systems don't map to each other, and you get plenty of cases where
the two simply don't map. John is talking about all E_WARNINGs in
OO code, and in the procedural variants, sending E_WARNINGs. The
scope ofE_WARNING
is not in my opinion the same scope as an exception
in any language, and we may just have to agree to disagree.
The not-mapping issue is a serious one. PHP's procedural
error-handling does not map well to Java or Python. PHP's OO
error-handling can. The former can't change, the latter can. I don't
think there's a clean answer. And before I incur a rant from Sascha
about how I ramble endlessly without point, I'll resign from this
argument.
George
Exceptions in languages like Java are used explicitly to catch fatal
errors, not to catch basic errors. Converting warnings to exceptions
would change the meaning of a warning from something which is nice for
development, or logging purposes, but handled by your control flow, into
an unrecoverable error.
Exceptions enable the user (as in: the programmer as user of a certain
API) to decide which conditions qualify as fatal and which do not. For
example, an SQL parse error would be fatal in an app where the SQL is
hardcoded, but would be a valid error condition in an app that allows
user entry of SQL statements. Stating here which errors are fatal and
which are not is therefore pointless.
Being able to only handle the error conditions that you can reasonably
expect, and ignore the others, is the whole purpose of providing
exception handling in the first place. Having the whole PHP OO API
return false for every error without giving the nature of the error
defeats this purpose entirely.
Therefore, IMO, proper implementation of exception handling should at
least provide exception functionality for the entire OO API, and maybe
even for the procedural API as well, as they're not interchangeable,
meaning OO apps will use the procedural API as well.
I'm well aware that this is not going to happen, so maybe a compromise
would be possible. Perhaps a zval type IS_ERROR that evaluates to FALSE
for most common purposes, but can be used to identify the actual error
condition that occurred, or the ability to pass more context to a
user-defined error handler could be considered ?
And for the E_WARNINGs, maybe a built-in Exception specialization (ie.
NonFatalException) that is ignored by the top level catch() ?
--
Ard