Staying focused on problem solving can get difficult when new technologies offer tempting distractions. The most frequently heard buzz words are Java, C++ and Object Oriented Programming (OOP). Java promoters sometimes make it sound as if Java created Objected Oriented Programming. In fact, the AS/400 operating system has always been object oriented. Not only that, many of the goals of OOP are achievable using RPG and CL. Modular programming and encapsulation are a couple of the intimidating sounding concepts that are part of OOP. In this article, I will present the simple techniques of passing parameters with CL and RPG that make modular programming and encapsulation possible.
Encapsulation simply describes the notion that if a program is called by passing parameters to it, and if the program produces the correct results, the internal workings of the program are not important. You don't even need the source code of the program as long as the parameters and function of the program are well documented.
For example, you may wish to write a program to search for a customer number based on the customer's name. This program would be called with two parameters. The first parameter is the customer number. The second is a parameter that indicates if the user successfully found the customer. After all, the user may look for a customer and not find it.
On the AS/400 there are several ways to pass parameters. An old style of programming was to store the parameters in the Local Data Area and have the called program retrieve the values from there. In RPG, the most direct and widely used way of passing parameters is with a parameter list. The parameter list is coded as a PLIST operation in a C specification. It can be anywhere in the program but the most logical place is at the beginning of the C specs. In the customer search example, the PLIST is:
C *ENTRY PLIST C PARM PCUST 5 0 C PARM RTNCOD 1The value *ENTRY tells the program that the following parameters are expected whenever this program is called. When this program begins execution, it will populate the variable PCUST with the first parameter and RTNCOD with the second parameter. In this case, both of these parameters will provide information for the calling program. Later, I'll discuss a program that uses the parameter to get information from the calling program.
The rest of the customer search program is a sub-file program that lets the user select the customer number from a list of customer names. Figure 1 shows the part of the RPG program that handles the parameters.
The PLIST statement defines the parameters that are used when the program is called. Before the RETURN statement, the program moves the selected customer number to PCUST. This value is passed back to the calling program along with the RTNCOD field that tells whether a customer number was selected.
This program can be called anytime a user needs to be able to search for customer number by name. The user can be given the choice of using a function key to call the program from almost any screen that uses the customer number field. This is the essence of modular programming. You are reusing a program many times without having to modify or debug the customer search logic.
Suppose the accounts receivable department would like to selectively print statements of individual customers. Figure 2 shows the parameter handling part of the RPG program that prints the statement. It uses the customer number as its only parameter. When this program is called, it will print a statement for that specific customer.
Figure 3 shows the CL program to print the statement. It overrides the print file to go to the printer that is used to print statements, PRTARSTMT. The CL is called with the customer number as its only parameter. It then calls the RPG program to print the statement for this customer.
The parameter for the CL program is specified at the beginning in the PGM statement. Since a parameter is a variable, it must be declared using a DCL statement. As always, the attributes of the variable must be the same as the variable in the calling program.
Figure 4 shows the CL program that ties all the programs together. Calling this program will:
Similarly, a program that is called with a parameter is essentially told, "When you start executing, first use this value for the field specified in the PLIST or the PGM statement".
If you concentrate on writing programs that are modular and parameter driven, you will find yourself reusing programs more and more. As you do, you will see how easy it is to add features to programs by simply adding CALL statements. The best part is that you will not have to change or debug the called programs because they have hopefully, already proven to be bug free.
Figure 1 - This is the part of the RPG Customer Search program that handles the parameters. C *ENTRY PLIST C PARM PCUST 5 0 C PARM RTNCOD 1 * * Execute the CustSearch routine to let the user look up the * customer by name - that customer # is CSCUS# C EXSR CustSearch * If Indicator 3 is on, the user did not select a customer C *IN03 IFEQ *ON C MOVE 'N' RTNCOD C MOVE *ZERO PCUST C ELSE C MOVE 'Y' RTNCOD C MOVE CSCUS# PCUST C ENDIF C MOVE *ON *INLR C RETURN Figure 2 - This is the parameter handling part of the RPG program that prints the statement. This is the part of Statement Print program that uses the parameter. C *ENTRY PLIST C PARM PRTCUS 5 0 * * Look up the Customer # from the CUST file and print the * customer's statement * C PRTCUS CHAIN CUST 80 * C *IN80 IFEQ *OFF C EXSR PrintStmt C ENDIF * C MOVE *ON *INLR C RETURN Figure 3 - This is CL program that prints the statement to the PRTARSTMT printer. /* This program calls the RPG program STMR002 which will */ /* print the statement for the customer specified in the */ /* CALL statement in the CL program STMC002 */ PGM PARM(&CUST) /* The field in the PARM portion of the PGM statement must be */ /* declared and must be the same length and type as in the */ /* calling program. */ DCL VAR(&CUST) TYPE(*DEC) LEN(5 0) OVRPRTF FILE(QPRINT) DEV(PRTARSTMT) /* Call the Statement Print program to print this cust's stmt */ CALL PGM(STMR002) PARM(&CUST) ENDPGM Figure 4 - This is the CL that ties all the programs together. /* This program lets the users search for a customer */ /* and then runs a batch job to print the statement for */ /* that customer. */ PGM DCL VAR(&CUSNUM) TYPE(*DEC) LEN(5 0) VALUE(0) DCL VAR(&PRTSTMT) TYPE(*CHAR) LEN(1) VALUE(' ') /* First, call program for user to search for a customer */ CALL PGM(STMR001) PARM(&CUST &PRTSTMT) /* If user selected a customer, submit the job to */ /* print the statement for this customer. */ IF COND(PRTSTMT = 'Y') + THEN(SBMJOB CMD(CALL PGM(STMC001) PARM(&CUST))) ENDPGM