I haven't programmed Java for a while, so I missed that development. Back when I learned it this didn't exist yet, or at least was rarely used.
Yes agreed, database libraries seem to be notably bad in exception reporting. In Python, even though SQL is wrapped in a general layer, exceptions are still different per engine. MySQL has one exception with an error code which makes it very hard to distinguish between even a duplicate key and a network error.
Another mistake that many libraries make is that they make a generic 'FooLibraryException' and subclass all their exceptions from there, instead of from where it makes sense (IoError, KeyError, MemoryError ...)
But even with those issues, I hugely prefer exceptions to the 'check return value after every call'.
"Another mistake that many libraries make is that they make a generic 'FooLibraryException' and subclass all their exceptions from there, instead of from where it makes sense (IoError, KeyError, MemoryError ...)"
Actually, this isn't black and white. When I need to create more than one exception class for a library, I prefer to avoid subclassing standard exceptions to prevent that kind of confusing situation:
If my_library was returning a IOError, you would not know if the problem came from your code or the library code. Moreover, this would leak implementation detail.
Of course, you can always get around this by wrapping each library call within a try/catch block, but that does not scale well if you make many calls interspersed with your code.
Well, at least from a maintainability perspective it's more clear to do
try:
afile = open('myfile.txt')
content = afile.read()
except XXX:
(handle exception)
else:
(continue here using content)
If you want to capture the exceptions from a certain call. Otherwise, my_library.do_something might start raising a IOError somewhere in its bowels later on, and you have a confusing debug process.
When you find that you have a lot of similar or even repeated try/catch blocks, using 'with' context managers might be a good idea.
My point was that an IOError is an IOError, wether it's a MongoDBIOError or a MySQLIOError. Yes, you leak some implementation detail (namely, that I/O is used) but do do useful diagnostics you need some (abstract) implementation knowledge... network error: is your router plugged in? io error: is the disk full? keyerror: implementation bug? and so on.
Hm maybe this would be a case for multi-inheritance exceptions? MongoDBIOException is both and IOException as a MongoDBException. Don't even know if it's possible, or wise :)
Yes agreed, database libraries seem to be notably bad in exception reporting. In Python, even though SQL is wrapped in a general layer, exceptions are still different per engine. MySQL has one exception with an error code which makes it very hard to distinguish between even a duplicate key and a network error.
Another mistake that many libraries make is that they make a generic 'FooLibraryException' and subclass all their exceptions from there, instead of from where it makes sense (IoError, KeyError, MemoryError ...)
But even with those issues, I hugely prefer exceptions to the 'check return value after every call'.