Tip use of constants when testing return values

You have probably seen the recommendation to use "readable" constants rather than numbers.

The examples given in this trick are related to the different status returned by the database Read, Write, Delete... operations.

Another example is the status returned (in the ASTATUS variable) by all the methods. The different returned values correspond to the level of the error severity : '0' meaning that there is no error ([V]CST_AOK), '1' corresponds to an information returned ([V]CST_AINFO)... The higher the code is, the more severe is the situation.
Anyway, you don't care about the real value of these constants. As soon as they are checked by the corresponding '[V]CST_Axxxx' constant, you do not care about them any longer. The only interesting point is that you can consider that any status lower than '[V]CST_AERROR' is not a blocking error, and any status higher than '[V]CST_AOK' might at least require a warning.

In the supervisor libraries, the standard return is zero ([V]CST_AOK) when no error occurs; but frequently, in the application code, developers have libraries that return an identifier equal to null if the operation failed. This gives code examples like the following one:

Local Integer ID
  ID=Func MYORDER.PERFORM_OPERATION
  If ID
    # The operation has been successful and a valid ID has been returned
  Else
    # The operation failed
  Endif

The If RETURN_VALUE or its negation If ! RETURN_VALUE are therefore very popular and should not be changed, because the code is much more readable than a complex condition.

The recommendation that can be made is more to clearly identify in the subprogram the case where an error is raised by returning a null value. Rather than writing End 0, it is much more readable to use the constant [V]CST_AFALSE in this case. And if the operation returns only a status ( true or false ), we can also use [V]CST_ATRUE. For example:

Subprog CHECK_CREDIT_LIMIT
Local Decimal CREDIT,TRESHHOLD, UNPAID_AMOUNT
# Let's first compute some values
...
# The final test
If CREDIT>TRESHHOLD or UNPAID_AMOUNT>0
  End [V]CST_FALSE
Endif
End [V]CST_ATRUE

Other interesting examples are subprograms that return dates or character strings that are null when an error occurs. Instead of using [0/0/0] and "", it is now possible to use the AVOID instance. This is valid for both subprogram and func call. Let's have an example:
 Local Date DELIVERY_DATE
 DELIVERY_DATE = Func NEXT_AVAILABILITY(PRODUCT, QUANTITY, SITE)
 If DELIVERY_DATE=GACTX.AVOID.ADATE
   # Product is no more available
 Else
   # Product is available at the date given by DELIVERY_DATE
 Endif
...
Funprog DELIVERY_DATE(PRODUCT, QUANTITY, DATE)
....
 If QUANTITY>AVAILABLE_QUANTITY and QUANTITY>AVAILABLE_QUANTITY+EXPECTED_RECEPTION
   End GACTX.AVOID.ADATE
 Endif
...