Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this an abuse of try/finally?

Given that multiple return statements are acceptable (I sort of disagree, but let us digress), I'm looking for a more acceptable way to achieve the following behavior:

Option A: multiple returns, repeated code block

public bool myMethod() {     /* ... code ... */      if(thisCondition) {         /* ... code that must run at end of method ... */         return false;     }      /* ... more code ... */      if(thatCondition) {         /* ... the SAME code that must run at end of method ... */         return false;     }      /* ... even more code ... */      /* ... the SAME CODE AGAIN that must run at end of method ... */     return lastCondition; } 

It makes me feel dirty to see the same (little) code block repeated three times each time the method returns. Furthermore, I would like to clarify that the two return false statements above can certainly be described as returning mid-method... they are absolutely not "guard statements."

Is Option B slightly more acceptable? I feel that I may abusing try/finally, and I'm hoping there is something completely different that I should be doing.

Option B: multiple returns, try/finally block (without catch blocks / exceptions)

public bool myMethod() {     try {         /* ... code ... */          if(thisCondition) {             return false;         }          /* ... more code ... */          if(thatCondition) {             return false;         }          /* ... even more code ... */          return lastCondition;     } finally {         /* ... code that must run at end of method ... */     } } 

Finally, Option C is the best solution in my book, but my team doesn't like this approach for whatever reason(s), hence I'm looking for a compromise.

Option C: single return, conditional blocks

public bool myMethod() {     /* ... code ... */      if(!thisCondition) {         /* ... more code ... */     }      if(!thisCondition && !thatCondition) {         /* ... even more code ... */     }      /* ... code that must run at end of method ... */     return summaryCondition; } 

If you want to discuss multiple return statements, please do so in this question.

like image 311
Dolph Avatar asked Feb 09 '10 16:02

Dolph


People also ask

Can we use finally with try?

What Is finally? finally defines a block of code we use along with the try keyword. It defines code that's always run after the try and any catch block, before the method is completed. The finally block executes regardless of whether an exception is thrown or caught.

Can we use try finally without catch?

Yes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.

What does try finally do?

By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement.

What is the point of finally in try catch?

The purpose of a finally block is to ensure that code gets run in three circumstances which would not very cleanly be handled using "catch" blocks alone: If code within the try block exits via return.


1 Answers

If the code needs to run even when any other code throws an exception, then the finally block is the correct solution.

If it need not run in the case of an exception (i.e. it's only necessary for "normal" returns), then using finally would be abusing the feature.

Personally I'd rewrite that method in the single-return-point style. Not because I religiously subscribe to that idea (I don't), but because it is best suited for these kind of end-of-method codes.

When that code turns out to be overly complicated (and that's a very real possibility), then it's time to refactor the method by extracting one or more methods.

The simplest refactoring would be something like this:

public boolean  myMethod() {     boolean result = myExtractedMethod();     /* ... code that must run at end of method ... */     return result; }  protected boolean myExtractedMethod() {     /* ... code ... */      if(thisCondition) {         return false;     }      /* ... more code ... */      if(thatCondition) {         return false;     }      /* ... even more code ... */     return lastCondition; } 
like image 115
Joachim Sauer Avatar answered Sep 27 '22 17:09

Joachim Sauer