Programming with Assertions
April 21, 2004 Cletus the Codeslinger
I am amazed to see how much programmers take for granted. For example, I have worked on many programs in which the author had assumed that an RPG CHAIN operation (a random read) would always find the sought-for record. Occasionally I have to fix a program that ended abnormally because it attempted to divide by zero. The authors of such programs assumed that the divisor would never be zero, but somehow such a thing happened.
To help deal with the problem of assumptions, I have been using assertions in my code. An assertion is a program statement that tests an assumption and, if that assumption is not true, protests loudly. I understand that assertions come from the world of C programming.
A typical assertion routine accepts two arguments. The first one is a condition that is always assumed to be true. The second is an error message to be sent to the user if the first argument turns out not to be as true as was previously thought. Here is an assertion routine I wrote in RPG IV.
* ============================================================= * Abruptly end the program if an unexpected condition arises. * ============================================================ P Assert B D Assert PI D Condition N Value D Message 80A Value D SendEscMsg PR ExtPgm('QMHSNDPM') D MsgID 7 Const D MsgFile 20 Const D MsgDta 80 Const D MsgDtaLen 10I 0 Const D MsgType 10 Const D MsgQ 10 Const D MsgQNbr 10I 0 Const D MsgKey 4 D ErrorDS 16 D ErrorDS DS 16 D BytesProv 10I 0 inz(16) D BytesAvail 10I 0 D ExceptionID 7 D MsgDta S 80 D MsgKey S 4 /FREE IF (not Condition); *inlr = *on; SendEscMsg ('CPF9898': 'QCPFMSG QSYS': Message: %len(Message): '*ESCAPE': '*PGMBDY': 1: MsgKey: ErrorDS); ENDIF; RETURN; /END-FREE P Assert E
Here’s the prototype:
D Assert PR D Condition N Value D Message 80A Value
Since the first parameter is passed by value, you can use any type of expression that yields a true or false value. The second parameter is also passed by value, so it can be any expression that creates a character string.
My assert routine sends an escape message, which terminates the program immediately. You may prefer something less drastic.
Let’s return to the assumptions I mentioned earlier. If you think a CHAIN will never fail, you might include an assertion after the CHAIN.
/FREE CHAIN %KDS(CustKey) Customer; Assert (%FOUND: 'Customer ' + %CHAR(CustKey.Company) + '/' + %CHAR(CustKey.CustNbr) + ' was not found in the Customer file'); /END-FREE
Here is the same example using more traditional RPG coding techniques.
CL0N01Factor1+++++Opcode&ExtFactor2+++++Result++++++Len++D+HiLoEq.... C CUSKEY CHAIN CUSTOMER 95 C CALLP Assert C (*IN95 = *OFF: C 'Customer ' + C %CHAR(COMPANY) + C '/' + C %CHAR(CUSTNBR) + C ' was not found in the Customer file')
If you think that a field will never be zero, you might use this type of assertion.
/FREE Assert (Balance <> *zero: 'Balance was zero in order ' + %CHAR(OrderNo)); Average = Sum / Balance; /END-FREE
To force an assertion, pass the value *OFF in the first parameter. The following assertion is activated if no WHEN clause in a SELECT group proves true.
/FREE SELECT; WHEN CustClass = '01'; WHEN CustClass = '02'; WHEN CustClass = '03'; OTHER; Assert (*OFF: 'Invalid customer class: ' + CustClass); ENDSL; /END-FREE
I find assertions are more valuable during testing than in production. I may use an assertion to verify that a field is not negative, but eventually I replace the assertion with error-handling logic. However, if my error-handling logic is to cancel the program with an escape message, I keep the assertion.
Since assertions are usually for testing only, I sometimes condition them using a compiler directive. Here the assertion is compiled only when the TESTING condition is defined.
/FREE SELECT; WHEN CustClass = '01'; WHEN CustClass = '02'; WHEN CustClass = '03'; /IF DEFINED(TESTING) OTHER; Assert (*OFF: 'Invalid customer class: ' + CustClass); /ENDIF ENDSL; /END-FREE
There is plenty of material about programming with assertions on the Web. You can find a good article written from a Java perspective on Sun’s Web site.