Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

The finally block for a try-catch structure is well known, and gives a really easy and elegant way to deal with some must-be-done code.

Therefore, I can see no reason why It shouldn't be good for methods too. For instance, lets say I'm writing some very complicated logic in a method, and I expect to end up with a bunch of boolean flags that will in turn lead to some decisions. Many times in such kind of methods I have branches of code where I would want to "break" the flow and just perform the "real stuff" that I called this method for, with the satisfying information I gathered so far.

So, Why isn't there such pattern? Or is there?

share|improve this question
1  
Many languages have goto for that. –  johannes Jun 20 '13 at 22:14
9  
Using "a bunch of boolean flags" is a red flag that you're approaching your logic incorrectly, and you will benefit from refactoring your approach to the control flow in question. This is also why there's no need for such a "pattern" on functions. –  Matt D Jun 20 '13 at 23:30
    
After getting the above answers (and some others in SO where the question was originally posted) I conclude that it could indeed be a good idea, and probably programmers fear from new concepts, or rather fear to admit that their favorite language is flawless... Thanks @johannes for pointing out the different way to achieve such behavior. Whould have vote up if I had the privilege. –  Elist Jun 21 '13 at 8:20
    
If I understand your question correctly you can simply put the decision logic in a separate function, and return when you want to "break the flow and perform the real stuff". –  lortabac Jun 21 '13 at 9:07
1  
Cross-posted: stackoverflow.com/questions/17223949/… –  Matt Fenwick Jun 21 '13 at 9:41
show 2 more comments

7 Answers

up vote 8 down vote accepted

The first thing is: Don't have too complex functions doing to complicated things. If you can't avoid complex functions there are different tools to handle the situation.

In C and other languages people often use goto for the reason.

void func() {
    /* .. code .. */
    if (condition()) goto end;
    /* ... more code ...*/
end:
    cleanup();
}

Now some people don't like goto, even in such cases so they emulate goto using a do { . } while(0) loop:

void func() {
    do {
        /* .. code .. */
        if (condition()) break;
        /* ... more code ...*/
    } while(0);
    cleanup();
}

some languages, for instance PHP allow giving a parameter to the break paramter to jump multiple levels out:

function func() {
    do {
        /* .. code .. */
        if(something() {
          /* some code */
          if (condition()) break 2;
          /* ... */
        }
        /* ... more code ...*/
    } while(0);
    cleanup();
}

but there are languages with more highlevel constructs. C++ for instance has destructors, there people use the RAII pattern

struct cleanup {
    ~cleanup() {
        /* .. do cleanup ... */
    }
 }

void func() {
    cleanup cleaner; // this stack object will be destroyed on exit, for that the destructor is being called
    if (condition()) return;
    /* ... more code ...*/
}

Some other languages don't have goto and don't have nested break and no destructors, so Java programmers have to live with nested if's ore use exceptions ... or make the code simpler.

public static void func() {
    try {
        /* .. code .. */
        if(something() {
          /* some code */
          if (condition()) throw new ControlFlowException();
          /* ... */
        }
        /* ... more code ...*/
    } catch (ControlFlowException e) {
        /* ignore */
    } finally {
        cleanup();
    }
}

So yes, concepts exist and differ by language.

share|improve this answer
    
+1 for the wide and enlightening review of languages, but I'm still not convinced this shouldn't be a standard way to "destruct" methods. goto can make the code unreadable, and the other ways are just tricks. –  Elist Jun 20 '13 at 22:38
    
Yes, goto can be abused, so can be if clauses and for loops. Having clear distinct jumps in such situations is (imo) a proper use, though. On the others: Sure in a way they are hacks, but adding a specific language construct to languages makes the languages more complicated for the sake of a functionality that should be avoided by writing smaller functions in the first place. –  johannes Jun 20 '13 at 23:13
    
This cleanup pattern can also be implemented using two functions. int func_with_cleanup() { int exitcode = func(); if (!exitcode) cleanup(); return exitcode; } int func() { ... } –  rwong Jun 21 '13 at 6:39
1  
Now some people don't like goto is a little understated, I guess. –  Uooo Jun 21 '13 at 8:37
1  
That Java example should be removed or corrected. Java does have nested breaks. See the language specification. –  COME FROM Sep 10 '13 at 10:01
show 4 more comments

My guess is that there isn't a huge need for that sort of feature for two reasons:

  1. Most languages already give you pretty explicit flow control with looping and branching constructs.
  2. One of the most common uses of finally is to ensure resources are safely disposed. If your method is so complicated that you need this, you should probably refactor it into more manageable pieces.
share|improve this answer
add comment

It's worth noting that C# has the using statement which will automatically call Dispose() on the object when it leaves scope. This includes disposing of it after a return statement, so it acts like a finally in that respect.

Note that this is tied to the object, not tied to the function. But it does handle the main usecase for a finally in a function.

share|improve this answer
1  
I don't know C# in that detail ... how does this compare to destructors in other languages? –  johannes Jun 20 '13 at 23:15
    
@johannes - See this SO answer. The short form is that the destructor is called at some arbitrary point when the object is garbage collected, but Dispose() should any managed resources right then. –  Bobson Jun 21 '13 at 5:44
    
Ah the wonders of Garbage Collection ... in C++ one knows when a destructor is called (explicit delete on heap, LIFO on stack) as does one i.e. with PHP when not using references (explicit unset or LIFO on function exit). Thanks for the link. –  johannes Jun 21 '13 at 9:58
add comment

The Go programming language has something similar to this idea: the defer statement. Deferred functions are called when the enclosing function exits for any reason, and can be method calls or plain functions, e.g.:

func fileProcessor(filename string) (err error) {
  var file *os.File
  if file, err = os.Open(filename); err != nil {
    return
  }
  defer func() {
    fmt.Printf("Closing file\n")
    file.Close()
  }()
  fmt.Printf("Processing file\n")
  return
}

In this case, the deferred function is anonymous. It could also just be:

defer file.Close()

But the anonymous routine allowed the Printfs in the example to highlight the order of execution.

In practice, I find defers to be a clean way to ensure the release of locally acquired resources. The approach isn't commonly found in other languages, but I find its presence in Go to be a welcome one, and would like to see it elsewhere.

share|improve this answer
    
It exists in D and ResourceT in Haskell –  jozefg Sep 17 '13 at 1:31
add comment

Extract method sounds like a good plan: break up you method into an "initialization" function, a "do your thing" function and a "finalization" function. That way the finalization will always be done regardless of what happens in "do your thing". Except in the case of exceptions of course, but that is where the finally block of your languages comes in. You would then put the "finalization" function in the finally block.

procedure MainFunction;
begin
  InitializationFunction;
  try
    DoYourThingFunction;
  finally
    FinalizationFunction;
  end;
end;
share|improve this answer
add comment

Does this really make your code more readable than alternatives? You could already put a try/finally around the code inside your function or you could put the "Finally" code right after the method is called.

Although it's a reasonable concept, every new feature you place into a language requires many many programmer hours of time to learn and understand--hundreds--thousands... If there is any way you can use an existing construct instead without causing a lot of duplication, boilerplate or confusion then it would be much better to use the existing mechanism.

share|improve this answer
    
I think such feature could be added without forcing any programmer to learn it or even know about it. Anyway, I don't think that confusing programmers should be a reason to not improving a language, when it doesn't break down the backward compatibility for already written code. programmers will get along, and new programmers will enjoy the benefit of a better language. –  Elist Jun 21 '13 at 8:18
    
Working with a team is different thatn working alone. You describe working alone (which is a perfectly valid scenario) but your assumptions don't apply to a team working on a largish project. If I code something using a new feature, my teammates (even overseas contractors) must know it (and there are always programmers anxious to try new language features, so it will happen). I think that when you are working alone you should just choose one of the many existing languages that have exciting, new constructs--you might be able to implement this feature in scala yourself, give it a try! –  Bill K Jun 21 '13 at 18:14
    
Thanks for the reference to scala. It looks interesting and I'll give it try. About working in team - I still think a reasonable, readable and self-explanatory feature will not be a problem. –  Elist Jun 22 '13 at 19:33
add comment

finally causes a lot of code repetition. If you use a resource Foo in 100 places, and the cleanup of Foo takes 3 lines, then the finally blocks would add 300 lines of code but a destructor adds only 3 lines total.

share|improve this answer
    
Funny that you allude to recommending destructors in that the only language I know that has them is C++, which does NOT have finally blocks. –  Thomas Eding Sep 16 '13 at 21:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.