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 IDID=Func MYORDER.PERFORM_OPERATIONIf ID# The operation has been successful and a valid ID has been returnedElse# The operation failedEndif

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_LIMITLocal Decimal CREDIT,TRESHHOLD, UNPAID_AMOUNT# Let's first compute some values...# The final testIf CREDIT>TRESHHOLD or UNPAID_AMOUNT>0End [V]CST_FALSEEndifEnd [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_DATEDELIVERY_DATE = Func NEXT_AVAILABILITY(PRODUCT, QUANTITY, SITE)If DELIVERY_DATE=GACTX.AVOID.ADATE# Product is no more availableElse# Product is available at the date given by DELIVERY_DATEEndif...Funprog DELIVERY_DATE(PRODUCT, QUANTITY, DATE)....If QUANTITY>AVAILABLE_QUANTITY and QUANTITY>AVAILABLE_QUANTITY+EXPECTED_RECEPTIONEnd GACTX.AVOID.ADATEEndif...