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 android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to