@BC_Programmer said:
I would say one way that this is mitigated as a problem is not to declare a checked exception of those types on an interface, but instead wrap checked exceptions in a new Exception class type, and declare that in that methods throws clause- so a interface for something that retrieves some data might have implementations that read from a file or Memory (which would have IOExceptions) or from the internet (which has another exception type) and so forth. Instead of declaring a method as "throws IOException,WebException...etc" instead a new Exception class is created that wraps that type- eg. "DataReadingException" or something, depending on the routine being used. This makes sense (IMO) because a consumer of the interface won't know specifically what went wrong, but might have a codepath to follow if something does, and this is more specific than a generic catch clause that catches everything, too.
We have a winner! Yes -- if your interface method is throwing IOException, WebException, SQLException, you are almost certainly exposing internal implementation details and should replace that with an exception at a higher level of abstraction. (I said this earlier in the thread, but maybe you didn't see it -- don't blame you, it's a pretty long thread at this point.)
@BC_Programmer said:
On the other hand, Exceptions are, as their name implies, for Exceptional conditions and we should be writing code to try to prevent them from happening in the first place- that is, take a proactive rather than reactive approach; Don't handle the exception where a file is not found, instead make sure the file exists before trying to call the method that would throw that Exception, etc. The Java approach seems to go with the idea that the Exceptions in some sense drive the program logic enough to have them declared as part of the method header.
This is why in Java there are two kinds of exceptions. Unchecked exceptions are the programmer's fault and indicate faulty logic. They are not declared because they are not part of the contract of the method. (Would you really like to see a "throws NullPointerException, IllegalArgumentException, NoClassDefFoundException" on a majority of your code? Didn't think so :).) Checked exceptions indicate things that can be expected to go wrong during normal execution of the method. As such they are part of the contract of the method, and just as an important and valuable part of its signature as its name, parameter types, and return type. So when I see "depositPaycheck() throws BankingServiceException, AccountException" I know that as part of its contract, depositPaycheck() is allowed to fail and there are two ways in which it can legally fail.
And yes, we should take steps to try to prevent exceptions from occurring -- but all the code in the world isn't going to help you if a rat gnawed through the network cable. Or somebody logged in as root runs "rm -rf /tmp" and deletes our working files.
@dhromed said:
So easy things
should be easy. Common things should be easy. Hard but common things
should be easy. Impossible things should be hard.
You missed (at least) one case. How about hard but uncommon things? And since impossible things should only be "hard", can I expect from a design for a perpetual motion machine soon? :-)
Redundantly,
Thomas