The final word on GOTO (Don't I wis

Kim Letkeman kim at kim.misemi
Mon Oct 2 23:32:01 AEST 1989


In article <5416 at merlin.usc.edu> jeenglis at nunki.usc.edu (Joe English) writes:
>kim at kim.misemi (Kim Letkeman) writes:
>>[blah blah blah]
>>As a general principle, writing a single procedure to perform a single
>>function (task) is the whole point behind so called structured
>>programming.  Coupling and cohesion and all that.
>>
>>So where does the goto fit after all this? It doesn't.
>What kind of control flow you use doesn't have
>that much to do with coupling or cohesion; the
>goto still has some valid uses.  For example:

You got me. I took a chance and mixed two points in successive
paragraphs without making my point particularly clear. I was really
trying to say that I feel that structured programming concepts are
adequate for the vast majority of situations and that gotos are only
necessary in extreme cases. I apologize for the lack of clarity there.

>void foo() {
>    int k;
>    initialization_sequence;
>
>    while (k = get_input()) {
>	 switch (k) {
>	   case 'A' : a_action(); break;
>	   case 'B' : b_action(); break; 
>	   ...
>	   case 'Q' : q_termination_stuff(); goto done;
>	   case 'X' : x_termination_stuff(); goto done; 
>	 }
>	 end_loop_processing;
>    }
>done:
>    cleanup_sequence;
>
>    return;
>}
>This, I submit, is an example of a cohesive function
>that uses a goto. If end_loop_processing and
>cleanup_sequence are nontrivial, this can't be cleanly
>done any other way.

I agree that this is an example of a cohesive function if the
end_loop_processing and cleanup_sequence is fairly trivial. If not, it
is likely that they are performing fairly significant functions that
are not entirely related to the actual running of the pseudo state
machine. In that case, they would be better isolated in their own
procedures. This improves cohesion and makes this procedure more
readable. (Your example is quite readable as shown, but would
deteriorate with additional code.)

>This example wasn't just invented to prove a point; I
>actually wrote something similar once.  (I shouldn't
>have said that...  now half the net will probably
>accuse me of dubious programming practices :-)

Just one (very quickly conceived) alternative:

void foo() {
    int k;
    int done;

    initialization_sequence (some parms?);   /* function if non-trivial */
    done = 0;
    while (k = get_input()) {
	 switch (k) {
	   case 'A' : a_action(); break;
	   case 'B' : b_action(); break; 
	   ...
	   case 'Q' : q_termination_stuff(); done = 1;
	   case 'X' : x_termination_stuff(); done = 1; 
	 }
         if (done) break;
	 end_loop_processing (some parms?);  /* function if non-trivial */
    }
    cleanup_sequence (some parms?);          /* function if non-trivial */

    return;
}

This version looks as good to me and if the case statement gets long
it means you don't get your "oh no ... a goto" bell rung every time
you encounter a termination situation. To make it read better, I might
use a state variable with readable names in an enumeration, or at
least constants like TRUE and FALSE. But the point is that this case
is not (IMO) extreme enough to warrant a goto.

>Another example of (I think) a valid use for the
>goto is the multi-level exception handling case
>posted a while back.

I believe someone posted a version without a goto. It looked fine to
me. 

>--Joe English

-- 
Kim Letkeman    uunet!mitel!spock!kim



More information about the Comp.lang.c mailing list