|
|
Home » Starter Kit » TOC » Chapter 24
Chapter 24 - CL Programming: You're Stylin' Now! The key to creating readable, maintainable code is establishing and adhering to a set of standards about how the code should look. Standards give your programs a consistent appearance -- a style -- and create a comfortable environment for the person reading and maintaining the code. They also boost productivity. Programmers with a consistent style don't think about how to arrange code; they simply follow clearly defined coding standards, which become like second nature through habit. And programmers reading such code can directly interpret the program's actions without the distraction of bad style. Good coding style transcends any one language. It's a matter of professionalism, of doing your work to the best of your abilities and with pride. Although most CL programs are short and to the point, a consistent programming style is as essential to CL as it is to any other language. When I started writing CL, I used the prompter to enter values for command parameters. Today, I still use the prompter for more complex commands or to prompt for valid values when I'm not sure what to specify. The prompter produces a standard of sorts. Every command begins in column 14, labels are to the left of the commands, and the editor wraps the parameters onto continuation lines like a word processor wraps words when you've reached the margin. While using the prompter is convenient, code generated this way can be extremely difficult to read and maintain. Let's look at CL program CVTOUTQCL (Figure 24.1), which converts the entries of an output queue listing into a database file. Another application can then read the database file and individually process each spool file (e.g., copy the contents of the spool file to a database file for saving or downloading to a PC). Without a program such as CVTOUTQCL, you would have to jot down the name of each output queue entry and enter each name into the CPYSPLF (Copy Spool File) command or any other command you use to process the entry.
Now compare the code in Figure 24.1 to the version of CVTOUTQCL shown in Figure 24.2. The programs' styles are dramatically different. Figure 24.1's code is crowded and difficult to read, primarily because of the CL prompter's default layout. In addition, this style lacks elements such as helpful spacing, code alignment, and comments that help you break the code down into logical, readable chunks. Figure 24.2's code is much more readable and comprehensible. An informative program header relates the program's purpose and basic functions. The program also features more attractive code alignment, spacing that divides the code into distinct sections, indentation for nested DO-ENDDO groups, and mnemonic variable names. Let's take a closer look at the elements responsible for Figure 24.2's clarity and some coding guidelines you can use to produce sharp CL code with a consistent appearance.
If the first source statement in your CL program is the PGM statement, something's missing. All programs, including CL programs, need an introduction. To create a stylish CL program, first write a program header that describes the program's purpose and basic function. Figure 24.2's program header provides the basic information a programmer needs to become familiar with the program's purpose and function. An accurate introduction helps programmers who come after you feel more comfortable as they debug or enhance your code. The program header begins with the program's name, followed by the author's name and the date created. An essential piece of the program header is the "program type," which identifies the type of code that follows. CL program types include the CPP (command processing program), the VCP (validity checking program), the CPO (command prompt override program), the MENU (menu program), and the PROMPT (prompter). You may use other categories or different names to describe the types of CL programs. But whatever you call it, you should identify the type of program you are writing and label it appropriately in the header. Another important part of the introduction is a description of what the program does. State the program's purpose concisely, and, in the program summary, outline the basic program functions to familiarize the programmer with how the program works. You should detail the summary only in terms of what happens and what events occur (e.g., building a file or copying records). A good program header also includes a revision summary, featuring a list of revisions, the dates they were made, and the names of those who made them.
If you don't have a standard CL program header, create a template of one in a source member called CLHEADER (or some other obvious name) and copy the member into each CL program. Fill in the current information for each program, and remember to maintain the information as part of the quality control checks you perform on production code. While an up-to-date program header is valuable, an outdated one can be misleading and harmful.
Determining where to start each statement is one of the most basic coding decisions you can make. If you're used to prompting each CL statement, your first inclination would be to begin each one in column 14. While you should use prompting when necessary to enter proper parameter values, the resulting alignment of commands, keywords, and values creates code that is difficult, at best, to read and maintain. Over the years, I've collected several guidelines about where to place code and comments within CL programs. For starters, begin all comments in column 1, and make comment lines a standard length. Beginning comments in column 1 gives you the maximum number of columns to type the comment. And establishing a consistent comment line length (i.e., the number of spaces between the beginning /* and the closing */) makes the program look neat and orderly. Comments should also stand out in the source. In Figure 24.2, a blank line precedes and follows each comment line to make it more visible. Notice that comments describing a process are boxed in by lines of special characters (I use the = character). Nobody wants to read code in which comments outnumber program statements. But descriptive (not cryptic) comments that define and describe the program's basic sections and functions are helpful road signs. A second guideline is to begin all label names in column 1 on a line with no other code (or at the appropriate nesting level, if located within an IF-THEN or IF-THEN-ELSE construct). Labels in CL programs serve as targets of GOTO statements. The AS/400 implementation of CL requires you to use GOTO statements to perform certain tasks that other languages can accomplish through a subroutine or a DO WHILE construct. (CL/free, a precompiler for CL that supports subroutines and other language enhancements, lets you create more-structured CL programs.) Because labels provide such a basic function, they should clearly reveal entry points into specific statements. Starting a label name in column 1 and placing it alone on the line helps separate it from subsequent code. Notice in Figure 24.2 how you can quickly scan down column 1 and locate the labels (e.g., GLOBAL_ERR, CLEAN_UP, RSND_BGN). However, notice the placement of labels RSND_RPT and RSND_END (at B and C). Instead of beginning these two labels in column 1, I indented them to the expected nesting level to promote comprehension of the overall process. The code following the indented labels remains indented to help the labels stand out and to make the IF-THEN construct more readable. To offset command statements from comments and labels, start commands in column 3. Beginning commands in column 3 -- rather than the prompter's default starting in column (14) -- gives you much more room to enter keywords and values. It also gives you more room to arrange your code. The exception to this guideline concerns using the DO command as part of an IF-THEN or IF-THEN-ELSE construct. To help identify what code is executed in a DO group, I recommend that you indent the code in each DO group. A simple indented DO-ENDDO group might appear as follows:
IF ("condition") DO
CL statement
CL statement
ENDDO
A multilevel set of DO-ENDDO groups, including an ELSE statement, might appear like this:
IF ("condition") DO
IF ("condition") DO
CL statement
CL statement
IF ("condition") DO
CL statement
ENDDO
ENDDO
ELSE DO
CL statement
CL statement
ENDDO
ENDDO
Notice that the IF and ENDDO statements -- and thus the logic -- are clearly visible.
When you use the prompter to enter values for command parameters, Source Entry Utility (SEU) automatically places the selected keywords and values into the code. Several simple guidelines can greatly enhance the way commands, keywords, and values appear in your CL programs. First, omit the following common keywords when using the associated commands: Command Keyword DCL VAR, TYPE, LEN CHGVAR VAR, VALUE IF COND, THEN ELSE CMD GOTO CMDLBL MONMSG MSGID The meanings of the parameter values are always obvious by position. Thus, the keywords just clutter up your code. The following statements omit unneeded keywords:
DCL &outq *CHAR 10 CHGVAR &outq (%SST(&i_ql_outq 1 10)) IF (&flag) GOTO FINISH GOTO RSND_RPT By starting commands in column 3 and following the indentation guidelines, you can type most commands on one line. But when you must continue the command to another line, you have several alternatives, as Figure 24.3 shows. The first alternative is to use the + continuation symbol, indent a couple of spaces on the next line, and continue entering command keywords and values. This is the simplest way to continue a command but the most difficult to read. The second alternative is to place as many keywords and values as possible on the first line and arrange the continuation lines so the additional keywords and values appear as columns under those on the first line. Although this option may be the easiest to read, creating the alignment is a major headache. The third alternative is simply to place each keyword and associated value on a separate line. This method is both simple to implement and easy to read. Thus, a second guideline is to place the entire command on one line when possible; otherwise, place the command and first keyword on the first line and each subsequent keyword on a separate line, using the + continuation symbol. A third guideline is to align the command and its parameters in columns when you repeat the same single-line command statement. This rule of thumb applies when you have a group of statements involving the same command. The DCL statement is a good example. Normally, one or more groups of DCL statements appear at the beginning of each CL program to define variables the program uses. Figure 24.2 shows how placing the DCL statement and parameter values in columns creates more readable code. This alignment rule also applies to multiple CHGVAR (Change Variable) commands. While you can apply the above rules to most commands, the IF command may require special alignment consideration. If the IF statement won't fit on a single line, use the DO-ENDDO construct. For example, the IF statement IF (&fl2exist) CRTDUPOBJ OBJ(QACVTOTQ) + FROMLIB(KWMLIB) OBJTYPE(*FILE) + TOLIB(&outlib) NEWOBJ(&outfile) should be written
IF (&fl2exist) DO
CRTDUPOBJ OBJ(QACVTOTQ) +
FROMLIB(KWMLIB) +
OBJTYPE(*FILE) +
TOLIB(&outlib) +
NEWOBJ(&outfile)
ENDDO
This construction implements guidelines discussed earlier and presents highly accessible code.
One of the most common symptoms of poor CL style is a general overcrowding of code. Such code moves from one statement to the next without any thought to organization, spacing, or neatness. The result looks more like a blob of commands than a flowing stream of clear, orderly statements. To save yourself and others the eyestrain of trying to read a jumble of code, follow these suggestions for clean, crisp CL programs: Align all + continuation symbols so they stand out in the source code. In Figure 24.2, I've aligned all + continuation symbols in column 69. Not only does alignment give your programs a uniform appearance, but it also clearly identifies commands that are continued on several lines. I use the + symbol instead of the - for continuation because the + better controls the number of blanks that appear when continuing a string of characters. Both symbols include as part of the string blanks that immediately precede or follow the symbol on the same line. But when continuing a string onto the next line in your source, the + symbol ignores blanks that precede the first nonblank character in the next record. The - continuation symbol includes them. Use blank lines liberally to make code more accessible. Spacing between blocks of code and between comment lines and code can really help programmers identify sections of code, distinguish one command from another, and generally "get into" the program. Blank lines don't cost you processing time, so feel free to space, space, space. Use the shorthand symbols ||, |<, and |> instead of the corresponding *CAT, *TCAT, and *BCAT operatives. Concatenation can be messy when you use a mixture of strings, variables, and the *CAT, *BCAT, and *TCAT operators. The shorthand symbols shorten and simplify expressions that use concatenation keywords and commands and clearly identify breaks between strings and variables.
lowercase names. An essential part of CL style concerns how you use variables in your programs. I don't have any hard-and-fast rules, but I do have some suggestions. First, consider the names you assign variables. Give program parameters distinct names that identify them as parameters. In Figure 24.2, the two parameters processed by the CPP are &I_ql_outq and &i_ql_outf. The i_ in the names tells me both parameters are input-only ( io_ would have indicated a return variable). The ql_ tells me the parameters' values are qualified names (i.e., they include the library name). When program CVTOUTQCL calls program CVTOUTQR, it uses parameter &io_rtncode (A in Figure 24.2). The prefix indicates the parameter is both an input and an output variable, and the rest of the name tells me program CVTOUTQR will return a value to the calling program. A second guideline concerns variables that contain more than one value (e.g., a qualified name or the contents of a data area). You should extract the values into separate variables before using the values in your program. In Figure 24.2, input parameter &i_ql_outq is the qualified name of the output queue. Later in the program, you find the following two statements: CHGVAR &outq (%SST(&i_ql_outq 1 10)) CHGVAR &outqlib (%SST(&i_ql_outq 11 10)) These two statements divide the qualified name into separate variables. The separate variables let you code a statement such as CHKOBJ OBJ(&outqlib/&outq) OBJTYPE(*OUTQ) instead of
CHKOBJ OBJ(%SST(&i_ql_outq 11 10)/ %SST(&I_ql_outq 1 10)) +
OBJTYPE(*OUTQ)
You should also define variables to represent frequently used literal values. For example, define values such as x, '', and 0 as variables &@x, &@blanks, and &@zero, and then use the variable names in tests instead of repeatedly coding the constants as part of the test condition. This guideline lets you define all of a program's constants in one set of DCL statements, which you can easily create and maintain at the start of the program source. In addition, notice the difference between the following statements: IF (&value = ' ') DO IF (&value = &@blanks) DO You can more easily digest the second statement because it explicitly tells you what value will result in execution of the DO statement. You may find that defining frequently used variables not only improves productivity, but also promotes consistency as programmers simply copy the variable DCL statements into new source members. A final guideline concerning variables is to type variable names in lowercase. The lowercase variable names contrast nicely with the uppercase commands/parameters. Although typing the names in lowercase may not be easy using SEU, the contrast in type will greatly improve the program's readability. Compare Figure 24.1 with Figure 24.2 again. Which code would you like to encounter the next time you examine a CL program for the first time? I hope you can use these guidelines to create a consistent CL style from which everyone in your shop can benefit. Remember: When you're trying to read a program you didn't write, appearance can be everything. Sidebar: CL Coding SuggestionsSidebar: Command, RPG program, and physical file associated with CL program CVOUTQCL shown in Figure 24.2.Starter Kit for the AS/400, 2nd Edition Copyright 1994 by Duke Press DUKE COMMUNICATIONS INTERNATIONAL Loveland, Colorado All rights reserved. No part of this book may be reproduced in any form by any electronic or mechanical means (including photocopying, recording, or information storage and retrieval) without permission in writing from the publisher. It is the reader's responsibility to ensure procedures and techniques used from this book are accurate and appropriate for the user's installation. No warranty is implied or expressed. This book was printed and bound in the United States of America. Second Edition: April 1994 ISBN 10882419-09-X |
| Sponsored Links | Featured Links | |
Penton Technology Media Connected Home | SQL Server Magazine | Windows IT Pro Report Bugs | Contact Us | Comments/Suggestions | Terms of Use | Privacy Statement | Trademarks See Membership Levels | Subscribe | Free E-mail Newsletters | Free RSS Feeds | My Profile | Upgrade Now | Renew Now © 2010 Penton Media, Inc. System i is a trademark of International Business Machines Corporation and is used by Penton Media, Inc., under license. SystemiNetwork.com is published independently of International Business Machines Corporation, which is not responsible in any way for the content. Penton Media, Inc., is solely responsible for the editorial content and control of the System iNetwork. |