Finally block for methods – is it a bad idea?

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?

7

The first thing is:
Don’t have too complex functions doing too complicated things.

If you can’t avoid complex functions, there are various other 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 dislike 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-keyword 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 higher-level 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
        // scope exit by calling the destructor
    if (condition()) return;
    /* ... more code ...*/
}

Some other languages have neither goto, nor nested break, nor destructors. Thus Java programmers have to live with nested if’s, abuse 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, alternative concepts exist and differ by language.

9

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.

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.

3

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 filen")
        file.Close()
    }()
    fmt.Printf("Processing filen")
    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.

1

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;

0

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.

5

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.

3

Some years later, several languages have a “defer” statement. Say you open a file, and you know you’ll need to close it eventually. So you write

Open file f
Defer close file f

The compiler guarantees that the defer statement will be called as late as possible. The good thing is that you can write the cleanup together with resource creation, at the point where the knowledge is there.

Actually, the TTCN-3 language was extended recently to support using finally and catch on function level.
Link to the standard

For example:

testcase t_myTest1() runs on myComponent {
  f_init("user1");
  f_init("unknown user");// bad argument will raise an exception in f_init
  ... // because of the raised exception execution continues in the finally block
} finally {
   ... // freeing up resources
}

Testcases have to be independent, without any side effects on each other.
At the same time, by their very purpose, they might uncover situations in the system under test, that might break their usual execution paths … but the resources allocated for the test would still need to be freed.

As such it makes sense for the language to offer a syntax that lets test developers achieve their aim (of freeing the resources), without having to put the logic of each testcase/function/etc… in a try-catch-finally block, which would just push the actual main logic of the test/function +1 level deeper.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật