This chapter describes how to write structured programs. In dealing with this subject, the application of structured programming to the modern RPG language is presented. The traditional approach to RPG programming has been to take advantage of the RPG cycle, indicators, and branching (i.e., GOTO). This approach has led to a stockpile of RPG programs that, to the new RPG programmer, are difficult to understand, hard to explain, and contain more comments than code. This has resulted in the inability of programmers to differentiate the logic portion of the program from the program process itself.
Structured programming is not new. The concept has been around since the early 1970s. RPG, born in the early 1960s, is even older than structured programming. The Modern RPG Language, released in 1978, is a relatively new language that includes many features necessary to write structured programs. The current version of RPG—RPG IV—contains a full set of structured programming constructs.
As more object-based programming practices are performed, RPG should be able to keep up with the latest in object-based programming. After all, the primary platform on which RPG is used (the IBM AS/400) has the original object-based operating system architecture that has been in use for over 20 years.
Programming itself is both an art (creativity) and a science. Structured programming is a method of programming. Programming methods are bred from learning experiences and practice—not from trends.
Programming style is a highly personal matter. Programmers solve programming problems much like mathematicians solve equations. Unlike mathematicians, however, few programmers agree on the best method for solving a problem. This is a primary cause for programming errors—programmers interjecting their own personality into the programs they're writing.
Like a general practitioner who must first go through internship and residency prior to becoming a family doctor, a programmer must first learn structured technologies and the vocabulary. Then the programmer must practice the art of structured programming before writing a major application using the structured approach.
The structured approach to program design consists of a set of related technologies for designing and writing application programs. Through a series of formulas and guidelines, these related technologies help reduce program errors while still providing for programmer creativity.
Some of the technology relating and contributing to structured programming include the following:
Structured Analysis. Structured analysis includes the techniques used to separate a system into base components. This allows the most complex problem to be broken down into simple items. Each item by itself becomes a simple programming task. When these tasks are properly combined, the complex problem is solved.
Structured Design. Structured design includes the methods used to take the results of the structured analysis (i.e., its components) and build program specifications. For example, a customer master inquiry application consists of a user interface, a full-record display panel, a multi-record list panel, and a method of querying the data.
Program Design. Program design includes the methods used to translate a piece of structured design into a series of program or module definitions. One example is the logic behind a customer master inquiry. Most programming errors are actually created in this phase. Poorly thought-out logic tasks that are too large and inflexible to communicate with other program modules are major causes of programming errors.
Top-Down Program Development. Top-down program development includes the technique used for developing programs in an incremental manner. The modules of a program design are broken down into individual functions or tasks. The program developer simply presumes each task will function properly, leaving lower-level analysis for later.
Top-down program design, by definition, is performed before any programs are written. Currently, several billion lines of RPG code exist. Most of this code was written before the introduction of structured constructs into RPG. With so many lines of code already written, there must be several billion lines of unstructured code already in existence.
As existing programs are maintained, structured programming constructs should be used to maintain the program code. These changes should be more readable and should greatly reduce the possibility of introducing errors into the program.
Naming conventions also are important. Clear and consistent names for fields, files, and routines should be used at all times. For example, you could name a procedure "Update an Order's Line Item" and name a field "Customer Number."
As a by-product, all names depict their unique function. A routine named "Update an Order's Line Item" performs the stated function.
To begin top-down development, first define the major requirements of the module being created. The customer master inquiry example could be broken down into six primary elements. See Figure 8.1.
Figure 8.1: Hierarchy chart of a top-down design.
The primary functions of the user interface of the customer master inquiry have been outlined without concern for the detail behind the functions. Once the functions have been specified, each can be treated as an individual, less-complex task. See Figure 8.2.
Step 1: Open the workstation device file. Step 1A: Send the prompt panel to the workstation. Read the user's request from the workstation. If 'EXIT' requested, end the program. Step 2: Parse the data the user has entered. Return the result to the main line. Step 3: If the parser returns a customer number: Retrieve the customer record. Display the customer data. Step 4: Else, if the parser returns search data: Query the customer file with the user's search criteria. GO TO Step 1A.
As shown in Figure 8.2, the outlining process can be used for top-down program development. The benefit of using an outline is that the programmer is led from the major functions of the structured programming design to the low-level program code. For example, to further define the basic steps in this design, the controlling logic's program code would be written as shown in Figure 8.3.
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++Len++DcHiLoEq 0001 C Open CustInq 0002 C Dou Function = 'EXIT' 0003 C ExFmt Panel1 0004 C exsr RtvMacro * Step 2 0005 C exsr Parse 0006 C TestN RqsData 5456 0007 C Move *IN54 CustRqs 0008 C Move *IN56 QryRqs * Step 3 0009 C CustRqs casEQ *ON DSPCST * Step 4 0010 C QryRqs casEQ *ON QUERY 0011 C EndCS 0012 C EndDo
As mentioned earlier, structured programming is a method of programming. The mere use of structured operations such as IF-THEN-ELSE, DO, SELECT-WHEN-OTHERWISE doesn't, in and of itself, constitute structured programming. Structured programming is the linking of a set of single-function routines that perform to the design specification. These routines are the result of structured analysis, structured design, and a top-down development specification.
A properly structured routine exhibits these characteristics:
One, and only one, entry and exit point is used. An escape clause is permitted, provided the escape clause branches to the one and only exit point.
All program code in the routine is necessary. No unusable code exists.
Infinite loops are absent from the routine.
Redundant code doesn't exist in the routine.
Only structured constructs are used for logic control.
Remember, however, that these are the outward characteristics of a properly structured procedure. The use of these characteristics as a guideline for programming routines doesn't warrant that properly structured routines are being written. In other words, don't confuse the results of hard work with the work itself.
The following rules should be known and respected when taking the structured approach to program development stage.
All procedures must be broken down into single-function routines. These routines consist of the lowest-level program code or program statements.
The function control routines (logic modules) contain conditional logical, testing, repetition, and flag setting.
The low-level functions (subprocedures) are controlled (i.e., called upon) by higher-level logic modules.
Low-level functions (subprocedures) are defined in one and only one location and are called upon whenever and wherever needed.
To achieve cohesion between the low-level modules, each routine performs one, and only one, task. The binding of the routines is controlled by high-level logic.
Remember, though, the mere use of structured operation codes doesn't mean well-formed structured programs are being written. They are only the tools used to write programs. The structure of those programs depends on the programmer.
According to a structured programming theorem, only sequence, choice, and repetition are needed to solve any logic problem. Sometimes, however, the efficiency of a procedure is achieved at the expense of structure. When a procedure or program has to conform to rigid size restrictions and still perform efficiently, techniques other than structured techniques may be required (i.e., the branch operation).
Structured programming consists of three components or constructs:
Sequence— The processes or operations of an application.
Choice— The decision or conditional logic of an application. This control structure is sometimes referred to as selection.
Repetition— The looping or consecutive rerunning of a sequence of operations. This construct is sometimes referred to as iteration.
The following sections offer descriptions and examples of each of these control-flow constructs.
Sequence is defined as one or more processes of an application. Flow passes from one process to another without concern. In the RPG language, a process can be a series of one or more successive operations: a subroutine, a subprocedure, or an entire program. For example, the "Update an Order's Line Item" routine shown in Figure 8.4 contains only sequence operations. Most RPG operation codes are considered sequence operations.
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++Len++DcHiLoEq C PriceItem BEGSR * Price an Order's Line Item C ORDQTY MULT Price Extension C Extension MULT DiscPrice Discount C SUB Discount Extension C ENDPrice ENDSR
Choice is defined as control structures or decisions that control sequence operations. If the decision is true, one path is taken. If the decision is false, a different path is taken. These control structures are known as IF-THEN-ELSE and CASE structures. The CASE structure is a special form of IF-THEN-ELSE. It provides a more readable method of composing thick nests of choice constructs. The SELECT-WHEN-OTHERWISE operations are used for this type of CASE.
The RPG language supports a third type of choice constructs with the CASxx (CASE) operation code. For example, the IF-THEN-ELSE control structure could be used to condition a pricing routine based on the item ordered being available and the quantity ordered being greater than zero (see Figure 8.5).
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++Len++DcHiLoEq C ITEM CHAIN ITEMMAST 54 C EVAL NotFound = *in54 C If (NotFound = *OFF) and (QtyOrd > 0) C Exsr PriceItem C endif
Table 8.1 lists the RPG operation codes that support the choice construct.
Operation | Description |
---|---|
IF | IF then ELSE... ENDIF. |
CASxx | Compare, then perform subroutine. |
COMP | Compare factor 1 to factor 2. |
CABxx | Compare factor 1 to factor 2, then branch. |
SELECT | Select — Begin an in-line case group. |
WHEN | Compare factor 1 to factor 2 in a case group. |
The COMP operation is typically avoided in modern RPG. The IF and SELECT-WHEN constructs are heavily used throughout most applications. The CASxx operation is used in applications where more traditional subroutines are included instead of the more modern subprocedures.
Repetition is defined as looping control of a sequence. A routine is performed a specified number of times, as long as a condition is true, or until a condition is true. The RPG language supports repetition with the DOWxx (DO WHILE), DOUxx (Do Until), DO (Do repeated), and FOR (Do repeated) operations. For example, the "Price an Ordered Item" routine shown in Figure 8.6 could price all items of an order by using the DOWxx construct for repetition.
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++Len++DcHiLoEq 0001 C ORDNBR Chain OrdFile 54 0002 C Eval eof = *IN54 0003 C Dow NOT (eof) 0004 C ORDQTY casGT 0 PRICEORDER 0005 C endcs 0006 C ORDNBR ReadE OrdFile 58 0007 C Move *IN58 eof 1 0008 C endDo
RPG includes several operations to perform repetition. These are traditional format operations and repetition operations that work with expressions. See Table 8.2.
Operation | Description |
---|---|
DO | DO... ENDDO (repeat process n times). |
DOU | DO UNTIL... ENDDO expression version (repeat process until condition is true). |
DOUxx | DO UNTIL... ENDDO fixed-format version (repeat process until condition is true). |
DOW | DO WHILE... ENDDO expression version (repeat process while condition is true). |
DOWxx | DO WHILE... ENDDO fixed-format version (repeat process while condition is true). |
FOR | FOR / ENDFOR expression version (repeat process n times). |
ITER | Iteration loop (stop processing DO loop at current step and branch up to the top of the DO loop to perform the next iteration). |
LEAVE | Leave loop (leave the DO loop by branching to the statement following the corresponding ENDDO operation). |
The FOR operation is used to repeat a series of program statements. There is a counter, limit, and increment value associated with each FOR operation. The counter can be incremented or decremented. In addition to standard expression syntax, the FOR operation supports the following infix operators:
BY -Identifies the increment or decrement value.
TO -Identifies the limit. The maximum value the index can be before the FOR loop ends.
DOWNTO -Identifies the limit. The minimum value the index can be before the FOR loop ends.
These three operators control the FOR loop. They identify two of the three components of a FOR loop. The entire FOR loop syntax is as follows:
0010 C FOR counter = start TO limit BY increment-value
or
0020 C FOR counter = start DOWNTO limit BY increment-value
The first line illustrates the traditional FOR loop structure: a start, an upper limit, and an increment value. This is effectively the traditional "FOR i = 1 to 10 by 1" syntax. The second line illustrates the decrement FOR loop. The decrement FOR loop starts at a higher value and decrements the counter on each pass through the FOR loop, as in "FOR i = 10 DOWNTO 1 by 1" syntax. Figure 8.7 illustrates the RPG IV code syntax of the FOR/ENDFOR loop.
.....DName+++++++++++EUDS.......Length+TDc.Functions++++++++++++++++++++++++++++ 0010 D Index S 5P 0 0020 D CustName S 35A Inz('The Lunar Spacecraft Company') .....CSRn01..............OpCode(ex)Extended-factor2+++++++++++++++++++++++++++++ 0030 C FOR Index = 1 TO %Len(CustName) by 1 0040 C If %Subst(CustName : Index : 1) = ' ' 0050 C Eval %Subst(CustName : Index : 1) = '_' 0060 C Endif 0070 C endfor
A program of structure results when coherent logic and organizational skills are used in the analysis and design phases of program development. Program language operation codes are used to build the low level of a program. For more information on all RPG operations, see chapter 5. These operations are essential in structured programming. While featured in chapter 5, they are reviewed here under the context of top-down structured programming.
The operation codes IFxx, CASxx, DOUxx, DOWxx, and WHENxx support Boolean operators. Boolean operators are used to control the type of relationship test that is performed between factor 1 and factor 2. The Boolean operators are listed in Table 8.3. The traditional RPG operations use the operator letters. In contrast, the modern operations (those supporting natural expressions) use the symbol form of the operator. The Boolean operator is appended to the operation code itself.
Operator | Symbol | Relationship Test |
---|---|---|
EQ | = | Factor 1 is equal to factor 2. |
NE | <> | Factor 1 is not equal to factor 2. |
GE | >= | Factor 1 is greater than or equal to factor 2. |
GT | > | Factor 1 is greater than factor 2. |
LE | <= | Factor 1 is less than or equal to factor 2. |
LT | < | Factor 1 is less than factor 2. |
Blank | N/A | Relationship test result is used to set on resulting indicators. |