Ask Reuben

GOTO

How can I automatically execute a MENU action ?

If you are like me, then you have probably learnt from an early age that the use of the GOTO statement should be discouraged.  I certainly discovered that on my own in my early days on a ZX-81 that using GOSUB was preferable to using GOTO.  Then I get to university and discover that there are concepts like Structured Programming that enforce that.  There  are papers like Donald Knuth “Structured Programming with GOTO statements” that show the use of GOTO was being debated before some of you were born.

Like anything, if you place constraints then you may force a less than optimal solution than if there were no constraints.

You might not have realised it, but before we introduced TRY/CATCH, you could have implemented the equivalent using GOTO and LABEL.   This is shown in this example shown in the TRY/CATCH documentation.

The following using TRY/CATCH

TRY
    SELECT COUNT(*) INTO num_cust FROM customers WHERE ord_date <= max_date 
CATCH
    ERROR "Error caught during SQL statement execution:", sqlca.sqlcode
END TRY

... could have equally been written ...

WHENEVER ANY ERROR GOTO catch_error
    SELECT COUNT(*) INTO num_cust FROM customers WHERE ord_date <= max_date 
    GOTO no_error 
LABEL catch_error:
WHENEVER ERROR STOP
    ERROR "Error caught during SQL statement execution:", sqlca.sqlcode
LABEL no_error

Hopefully you are in agreement that from a code readability point of view TRY/CATCH is preferable.

There is one place I have used GOTO in Genero code and that involves a MENU statement.  The design need was that if you entered the MENU and certain criteria were met, then execute a particular MENU item automatically to save the user having to select that Menu option for themselves.  That might have been because there was only one valid option.  The more common scenario was when you had the typical Informix Query/Add/Update/Delete/First/Previous/Next/Last/Exit menu (*).  If there were no records in the underlying table then it made sense to go straight to the Add and add a new record, whilst if there was one or more records then it made sense to go straight to the Query option to get the user to select some records.

One way to achieve this was to add some GOTO and LABEL  like so ...

MENU ""
   BEFORE MENU
      ...
      -- SELECT COUNT(*) INTO l_count FROM tablename
      IF l_count > 0 THEN
         GOTO lbl_query
      ELSE
         GOTO lbl_add
      END IF

   ON ACTION query
       LABEL lbl_query:
            ...
   ON ACTION add
       LABEL lbl_add:
            ...

The toughest thing about that solution was being able to determine a way that our automated code review would allow that allowed use of GOTO to slip through whilst blocking any other attempts from junior developers to use GOTO unreservedly.

Whilst I don't think you should allow unlimited use of GOTO it does have its place in a controlled manner.  It could be argued that a keyword is missing for the problem above, in the same way that TRY/CATCH was a new keyword that meant GOTO did not need to be used.

(*) is there a name for the Query/Add/Update/Delete/First/Previous/Next/Last/Exit menu pattern.  I call it the QAUD pattern