Your analysis is correct, but I can't agree with your advice.
Exceptions should generally be handled as far out as possible, for several
reasons.
First, handling them too far deep into your application limits your ability
to do anything useful about them.
Exception handling too deeply limits reuse. This might be an appropriate
place to retry, for example, depending on the contract for the method -- but
it would have to be the exact same policy for every use.
Exception handling too deeply means that EVERY caller must be aware of the
possibility that the method may not succeed, and check for and handle the
consequences. For example, if something returns null on failure, and you
store that value in a field -- this means you may then have to check
hundreds of references to that field! It is better to just throw out of the
entire body of code that expects the failing code to execute, so none of it
has to deal with the consequences of the failure.
Exception handling too deeply prevents consistent handling of unexpected
exceptions. For example, you can set up a single exception handler at the
top level entry points (lifecycle methods) of your activity, and report the
exception to the user, or log it, or send it to a server somewhere. You
can't do that if your exception handling consists of print statements
scattered in catch clauses scattered throughout your code.
But rather than declaring the method 'throws Exception', it's often better
to not declare any exceptions at all, and convert it to a RuntimeException.
try {
..bunch of code...
} catch (RuntimeException e) {
// Already a runtime exception, don't wrap it
throw e;
} catch (Exception e) {
// A non-runtime exception -- wrap it up and rethrow
throw new RuntimeException("Optional context-specific message here", e);
}
Also, the exception handling he wrote is convoluted and wrong. It's much
simpler to do it right, by matching try/catch blocks to the scope of the
objects and their exceptions:
public String getInternetData() throws Exception{
HttpClient client = new DefaultHttpClient();
try { // for the URISyntaxException
URI website = new
URI("http://www.rl.se<http://www.google.com/url?sa=D&q=http://www.rl.se&usg=AFQjCNE_VGoU2-sc5_LUFMZUQ4QRGXRv9A>
");
HttpGet request = new HttpGet();
request.setURI(website);
try { // For the IOExceptions actually communicating
with the client and processing the result.
HttpResponse response = client.execute(request);
BufferedReader In = new
BufferedReader(new InputStreamReader(response.getEntity().getContent()));
try { // To close the newly-opened stream
StringBuffer sb = new StringBuffer("");
String l = "";
String nl =
System.getProperty("line.separator");
while((l = In.readLine()) !=null){
sb.append(l + nl);
}
// This goes inside the try/catch, because it
only makes sense if we succeed to this point.
return sb.toString();
} finally {
In.close();
} catch (IOException ex) {
throw new RuntimeException("Could not communicate
with host: " + ex, ex);
}
} catch (URISyntaxException ex) {
throw new Error("Bad URI embedded in the program. I am a
buggy program, so I will throw Error instead of RuntimeException.", ex);
}
}
(Edited directly in my browser; my apologies if there are undetected errors
as a result. It should be adequate to illustrate the point).
Note you never had to put a variable outside a try/catch,initialize it to
null, set it inside, then check the variable. You almost never need to do
that, and when you think you do, you probably have your try/catch blocks
mis-configured. But sometimes, it means you need to break things out into
smaller methods with their own condition handling. We could have done that
with the URI parsing, for example, and converted that into an Error. That
routine could then be reused to handle all parsing of fixed URIs -- and this
routine would have one less try/catch block.
I didn't need to catch and rethrow RuntimeException (unlike my earlier
illustration) because I was able to catch a single exception class (which is
the common base class for all the non-runtime exceptions thrown). But if the
set is large, or something does throw Exception, then you should catch and
rethrow RuntimeException before catching Exception and repackaging as a
RuntimeException.
Finally -- IOException is a pretty specific exception, that a caller may
well be interested in. Rather than catching and rethrowing as
RuntimeException, I might simply declare the method to throw IOException,
and leave it to the caller to handle appropriately. That's because the
caller is likely to have an opinion about what to do about IOExceptions
specifically -- for example, report a problem with communicating with the
host. But that's a design trade-off -- you also make very caller responsible
for handling it. They can repackage as a RuntimeException if they wish, but
if that's all anyone is going to do, then handling here is simpler. I did it
here because it better illustrates my point; you should make that decision
based on a consistent policy for how you want to handle IO Exceptions when
communicating with the server.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en