Hello,
I too find the lack of finding exceptions that can be raised a
problem (I'm a nasty old Java programmer as well!). Java checked
exceptions get a beating every so often but it's not as bad as always
made out, see comments below:
One of my puzzlements about Java 10 years ago or so was
why it decided to go the "must declare every exception" route.
Well sort of there are two basic types of exceptions 'normal' exception
and runtime exceptions - runtime exceptions do not need a try/catch
around them. These are your general case.
Consider this simple and naive numeric integrator
def integrate(f, start, end, n):
delta = (end-start)/float(n)
x = start + delta / 2
sum = 0.0
for i in range(n+1):
sum = sum + f(x)
x += delta
return sum / (n+1)
That function cannot define all the exceptions that can be
raised because f itself can raise an arbitrary exception. Eg,
def f1(x):
return 1/max(5-x, 0)) # Can raise a divide-by-zero error
integrate(f1, 0, 10, 5)
Java handles that case by saying you don't need to declare
system exceptions.
Not exactly true, you do have to check some systems exceptions - all
those that are not runtime. Divide by zero, type exceptions, null
pointer exceptions are all examples of run-time. For the others see later.
Then consider
def f2(x):
fname = os.path.join("/cache/directory", str(x))
if os.path.exists(fname):
return float(open(fname, "r").read())
y = _f2(x)
outfile = open(fname, "w")
try:
outfile.write(str(y))
finally:
outfile.close()
return y
integrate(f2, 0, 10, 10)
If the file is not readable, or the directory not readable,
then this might raise an IOError.
How does the 'integrate' function declare that it can raise
any of the errors that the integrator function 'f' might raise?
Again, IOError might be considered a system-level error
such that it doesn't need declaring.
IOError is a checked exception - if you want to do IO then you need to
wrap it in a try catch or throw it to your caller. This is because IO
is inherently fault prone and you should be thinking about exceptions
and unusual cases when doing IO. However in Java, this sometimes falls
over for example - ByteOutputStream, writes to a byte array - because it
inherits OutStream, the read and write functions declare IOException
which means you do sometimes have to write a meaningless try catch for
this (its memory copying, won't fail due to IO).
Then change it to
polling some URL ("
http://cache.server/" + str(x)) when the
network is down, or getting it from some SQL database when
the password is incorrect, or anything else that cannot be
determined until actually calling f().
The first case uses OutputStream, checked exception - the second case
uses JDBC which also has checked exceptions.
It looks like the only thing to do is convert all such
unhandled exceptions and wrap them in a catch-all generic
exception. I think I've seen people do that. But if so,
what's the point of having typed exceptions?
Any java developer who does that should get pulled up at code review
time, the only time I could ever recommend that is in a top level call
when you want to catch all exceptions, log them and then apologise to
the user profusely that your program screwed up!!
Curiously-y'rs,
Andrew
(e-mail address removed)
On a general point, the python/adults thingy that is often said - if
followed correctly - removes the need for checked exceptions - if
everyone coded correctly then you wouldn't need it. However, I do find
it frustrating that in a lot of python docs - the exceptions that can be
thrown are not documented. I know there are obvious null pointers, key
errors and type exceptions but for example - what exceptions are thrown
if I call socket.recv(1024) when there are no characters for me to
receive?? The only way to determine this is to try it. I miss a level
of comfort that means that there may be a case which I haven't thought
of which could cause my code to go kablooeee. Eiffel's programming by
contract goes one step further...
Cheers,
Neil