Goto Design Pattern

(Original version)

You won’t find this anywhere else on the web (at least I couldn’t) and I can’t really explain why. Probably because patterns weren’t developed until after goto had been made ‘obsolete’ (by, as far as I can tell, continue and break).

But there is (at least) one common coding pattern which benefits greatly from the use of GOTO. I’ve titled it, Cascaded Initialisation.

Take, for example, a function which intialises a system. There are 2 parts of this system and part A must be initialised first. If part B fails to initialise then part A must be uninitialised. Quick and easy in C (example 1):

ret = init_A();  // bool ret = true for success, false for failure
if(!ret)
{
    return(FAILED);
}
ret = init_B();
if(!ret)
{
    uninit_A();
    return(FAILED);
}
return(SUCCESS);

Or, if we want to remove the multiple return points (example 2):

int return_value = FAILED;
ret = init_A();  // bool ret = true for success, false for failure
if(ret)
{
    ret = init_B();
    if(ret)
    {
        return_value = SUCCESS;
    }
    else
    {
        uninit_A();
    }
}
return(return_value);

The problem with these arrangements is what happens when there are more than about 3 parts. For the first one, each if(!ret) block will get longer and be repetitive, while the indenting in the second is going to become horrible.

The solution is to make the flowchart look like this:

And the code look like this (example 3):

ret = init_A();
    if(!ret) goto uninit_none;
 
    ret = init_B();
    if(!ret) goto uninit_A;
 
    ret = init_C();
    if(!ret) goto uninit_B;
 
    ret = init_D();
    if(!ret) goto uninit_C;
 
    return(SUCCESS);
 
uninit_C:
    uninit_C();
uninit_B:
    uninit_B();
uninit_A:
    uninit_A();
 
    return(FAILED);

Effectively the same as example 2 above. Much easier on the indentation, and on the condition that the labels are well named, much easier to read. You’ll notice that example 3 also has twice the amount of parts that the earlier examples did.

I challenge everyone to come up with a neater solution without using GOTO.