RPG and CL together form the nucleus of programming languages for the AS/400. It therefore seems only fitting that the RPG coding style guide presented in "The Essential RPG IV Style Guide" (June 1998) should have a companion guide for CL. In this article, I present just that: The Essential CL Style Guide. The guide is the result of a cooperative effort on the part of me, other NEWS/400 technical editors, and the participants in the CL forum at NEWS/400's Web site (http://www.news400.com), who reviewed and provided feedback on a draft of the guide you find here. (For a sampling of the forum's discussions, see "CL Style Online.")
Why Bother with Style?
There's much to be said for individuality, but when it comes to code, it's usually unwise to have as many styles as there are programmers. A single style based on a set of standards helps ensure your code is easy to read, understand, and maintain. Although adhering to standards may initially slow you down, within a short time you'll find that it actually results in faster development.
In developing your standards, it's important to keep in mind some key considerations. Among these are psychological constraints, such as the fact that we're conditioned to read in mixed case and to associate words that are next to or close to one another. There are also physical constraints, such as the size of your screen - you want to add white space for readability, but not so much that you can see only a few commands and parameters at a time. You'll be happier with the results of your efforts to develop standards if you take some time to think about considerations such as these before you begin.
Let's look at some suggestions to consider as you develop standards for your CL environment. As you peruse these guidelines, refer to Figure 1a for illustration. By the way, don't get hung up on trying to understand the sample code in the figure - it's a bit complicated! Just pay attention to the way it looks.
1.0 Comments
No doubt the notion of including comments in your code has been drilled into you more times than you care to remember. However, a closer look at some commenting guidelines might help you improve your technique.
|
CL Style Online |
|
|
Participants in NEWS/400's CL Forum (at http://www.news400.com) share their tips, techniques, and opinions about CL programming and coding style. Here's an excerpt from one of the exchanges on style in the forum. To read in full John Barron's proposal for an alternative, "minimalist" CL style, visit the forum. The Merits of CL Style John Barron: The basic assumption of the discussions in this forum has been that CL is a serious programming language and that the style of coding merits the same attention as in other languages. Taking the opposite view . . . leads to different results and a minimised set of standards. . . . CL code is (should be) generally "short and sweet" as described here. It is easy to read, understand, and maintain, because it does not (should not) contain complex logic, branching, and indentation, more than because of the coding style. Style and standards are needed, but it should be borne in mind that the finer nuances of detail in CL style gain little for the effort - only the broadest strokes of the brush are truly useful. . . . I'm explicitly *not* trying to suggest that there's any one right answer for all circumstances, or that the proposed CL style guide is always inappropriate. What I am trying to establish is: 1. There is a viable alternative to the all-encompassing proposed style guide for CL, which incidentally is also more or less what is successfully and satisfactorily used by many shops for commercial application CL code (i.e., not systems programming). 2. There can be reasonable justification for applying different degrees of emphasis to code style in different code languages for different uses. Here's an extreme example: I once worked for a company where as a matter of standard, deleting or directly amend[ing] lines of code was not allowed. All deletions were to be commented out, and all amendments [made] by commenting out the old code and entering new lines. . . . Then, rubbing salt into the wound, this was expected to apply to DDS (e.g., display file source) as well. Why? Because it's standard, so we must apply it to all kinds of source code. It starts to get very hard to use an otherwise invaluable tool like SDA under these circumstances. Much the same would be the case if we were to discuss using style rules as with CL and RPG for DDS source - either (prohibitive) re-editing would be necessary or the benefit of existing tools would be unavailable. In the case of CL and the command prompter, it's clearly not as extreme. However, the point that *all* re-editing is (by definition) an imposition and reduces the effectiveness of otherwise beneficial tools should stand demonstrated. Gary Guthrie: I agree with you that as a control language, CL is often short (or should be!) code that establishes an environment in which an application is to run. I also agree that with some system programming tasks, CL code can become larger and more complex. I would suggest that in the case where CL is short and sweet, merely establishing the application environment, then using "style" in your CL code wouldn't serve up the imposition you describe. On the other hand, when the CL code becomes more voluminous, "style" becomes increasingly important for understanding the code. . . . Standards can be very useful or they can be very demonic. I, too, have been in places where standards were used in the wrong way. I don't know if there's anything worse! All standards documents should be living documents. Things change with time, new ideas are brought forward, etc. There needs to be the flexibility to change standards when it is appropriate. Depending on the degree of the standards, there also need to be guidelines that allow for the possibility of deviating from the standards when necessary/appropriate. John Barron: I think this bears repeating in every set of standards. As a coder applying standards at the coal-face, I particularly appreciate the division of standards into "core" elements which are expected and "guideline" elements which are generally expected but where some discretion is permitted to the coder if there is a good reason for an exception. When I did work in an environment where I could reasonably say standards were seriously misused, the frustration level rapidly made me look for employment elsewhere, since I didn't make any headway getting things improved (no "flexibility" or "living documents" such as you suggest!). On every other occasion, there's been so much in shop standards that helps me that I've never found it hard to keep in line with them, unaffected by the odd minor element that I don't like (I think that's inevitable - no one likes everything in a set of standards). John Earl: I can relate to the use of standards as weapons. Standards are wonderful for helping us apply known solutions to problems we've already solved. And sometimes they can even be applied to problems we have never encountered before, but it's silly to try to make every new problem adhere to old solutions. Standards make sense only where levels of innovation are low or nonexistent, because innovation can be (and often purposely is) snuffed out by a slavish dependence on standards. | |
1.1 Use comments to clarify - not echo - your code. Remember that sometimes less is more. Good coding techniques help document your program, so simply repeating the code in your comments adds no value. Use comments to
1.2 Always include a brief summary at the beginning of a program. The program summary should include
There's a school of thought that says the program summary should also contain a chronology of changes that includes the date, programmer, and purpose of each change. You can include this information if you like, but it has been my experience that it's often ignored or erroneous. If you need to track program changes, a better alternative is to institute a change management system.
1.3 Use consistent "comment boxes" to divide major sections of code. To clearly divide sections of code by using comments, enclose the comments inside a "comment box." Never use one-line comments or comments embedded on the same line as code. Such comments tend to be overlooked, and they often lead to a cluttered appearance. Instead:
1.4 Use blank lines to group related code and heighten readability. When comments are unnecessary but you still want to divide sections of code, blank lines can be useful. Used in the right place, white space also makes your code easier to read.
2.0 Statement Alignment
Well-laid-out comments are only the first step in adding style to your CL programs. You can also take steps to maximize the readability of the CL statements in your code by improving on the way the prompter aligns statements.
2.1 Begin statements near the left margin. To accommodate labels in column 2, the prompter begins statements in column 14. You should instead relegate labels to their own line and start them in column 1. Begin CL commands in column 3 (or at the appropriate indentation level if the code is part of a DO structure or the continuation of a previous line). This practice maximizes the space you have for entering useful code on a line.
2.2 Align command parameters by allowing space for the maximum command length. When a command is shorter than the 10-byte maximum, leave sufficient blanks after the command to pad to the maximum length. Skip one more space, and then start the first parameter. For example, when a command begins in column 3, start the first parameter in column 14.
2.3 Use indentation to highlight dependencies. Use a consistent indentation factor (I prefer two spaces) for all statements you want to indent. For each nested level, increase the indentation by this factor.
2.3.1 IF statements. Place each IF condition on a line by itself (or on multiple lines if the condition uses *AND or *OR). On a continuation line, indent the command to be executed when the IF condition is true. If only one command is to be executed as the result of a test, don't follow the IF with a DO group; instead, execute the actual command. When an IF statement has an associated ELSE statement, align ELSE with IF. The segments of code at C, D, and H in Figure 1 illustrate these guidelines.
2.3.2 MONMSG/EXEC statements. When you use the MONMSG (Monitor Message) command's EXEC parameter, follow an alignment standard that indents the command to be executed in case of error on the line following the MONMSG, as at B in Figure 1. In the figure, MONMSG's EXEC parameter and opening parenthesis are placed at the right margin, with the closing parenthesis also at the right margin on a subsequent line. It would be nice if you could simply drop the EXEC keyword; unfortunately, it's required. By positioning EXEC and its parentheses out of the way like this, you further enhance your code's readability. Rather than follow this style, some programmers prefer to keep the EXEC keyword near the MONMSG command instead of at the right margin.
2.3.3 DO groups. Indent each statement that occurs between the DO and ENDDO commands of a DO group. Grouping statements this way makes it easy to tell which ones belong to the DO group.
2.4 Align command parameters. In many cases, you can fit a command and all its parameters on one line. When this isn't possible, place the first parameter on the line with the command. Code a continuation line for each subsequent parameter, and align it directly beneath the first one. Place the continuation character (+) to the right, aligned with the last character of your comment boxes.
2.5 For repeated one-line commands, align the commands and their parameters. Some commands (e.g., CHGVAR, DCL) are often repeated in succession and fit on a single line. When this is the case, align the commands and their parameters in columns (A).
2.6 Align continuation characters in a consistent column at the end of each line. This style not only gives your program a tidy appearance but also makes it easy to distinguish which commands are continued on subsequent lines. A quick glance lets you know whether a command is continued - no more hunt-and-peck missions looking for continuation characters.
3.0 Variable Names and Case
Many schools of thought exist on variable naming and whether to use upper, lower, or mixed case for various programming entities. Proper variable naming and proper case use greatly enhance your code's appearance and readability.
3.1 Avoid special characters in variable names. It's wise to avoid special characters (e.g., $, #) in variable names for several reasons. First, special characters can differ from language to language, and their use can lead to problems if your software ever runs on systems with different or multiple language features. Special characters don't "read" well, either. Isn't CstNbr (or CstNo) easier to interpret than Cst#? Likewise, don't prefix field names with special characters to signify information such as the fact that a field is from a display file. Not only is DspCstNbr or DspCstNo easier to read than $Cst#, but a prefix of Dsp rather than $ more clearly says that the field comes from a display file.
If those reasons aren't enough for you, special characters are harder to find on the keyboard! Okay, so that's not the greatest reason, but you get the point.
3.2 Construct meaningful variable names. If necessary, devise a naming convention that relies on abbreviations to represent particular entities. Then combine these abbreviations to construct meaningful variable names. OS/400 commands provide a good example of this type of structure with their verb/subject construction. Figure 1 shows some other examples.
3.3 Use mixed case. NEVER USE ALL UPPER CASE! It is perhaps the most difficult case style to read. If this style guide were presented in all upper case, you wouldn't even be reading this sentence - you'd have given up long ago! Likewise, all lower case can be hard to interpret.
Some stylists suggest using all lower case for variables and all upper case for everything else. Others suggest some other variant - upper case for this, lower case for that, mixed case for something else. But your goal should be to create readable code, not to emphasize the fact that a variable is a variable - you know it's a variable!
I suggest you use mixed case for everything. Code written this way looks neat and is by far the easiest to read. When you break down entities into multiple abbreviations, capitalize only the first character of each piece (e.g., variable &CmdStr for command string); when a name consists of only one element, capitalize just the first character of the name (e.g., variable &User for user).
4.0 Shortcut Dos and Don'ts
Shortcuts have their place in program code, but be sure to use them thoughtfully. For starters, never use a shortcut out of laziness. This tendency is a sure sign of a drop in quality. On the other hand, some shortcuts don't take away from quality and can actually make some parts of your CL programs easier to read.
4.1 Don't use shorthand symbols for concatenation operations. Avoid using the shorthand symbols ||, |>, and |< for CL's *CAT, *BCAT, and *TCAT concatenation operators. The vertical bar character (|) isn't readily available with some keyboard mappings. More important, though, the meanings of these symbols aren't as clear as the reserved words.
4.2 Simplify commands with obvious keywords. Some commands have obvious keywords and are easier to interpret when you omit the keywords altogether.
4.2.1 Simplifying PGM. Drop the PARM keyword on the PGM (Program) command, and enclose the parameter list in parentheses.
4.2.2 Simplifying DCL. On DCL (Declare CL Variable) commands, drop the VAR, TYPE, LEN, and VALUE keywords. Define the keyword values positionally, and enclose the LEN and VALUE parameters in parentheses. Leave enough space between the parentheses to enable LEN to contain the largest value possible (a four-digit number, a space, and two decimal positions). Figure 1 illustrates this rule at A.
4.2.2 Simplifying MONMSG. Drop the MONMSG command's MSGID keyword, and use parentheses to enclose the list of message IDs for which you're monitoring (B).
4.2.3 Simplifying CHGVAR. Omit the CHGVAR (Change Variable) command's VAR and VALUE keywords, and enclose the VALUE parameter in parentheses.
4.2.4 Simplifying IF. Drop the COND and THEN keywords from IF statements, and follow the alignment guidelines given above.
4.2.5 Simplifying ELSE. Drop the ELSE command's CMD keyword, and follow the alignment guidelines given above.
4.2.6 Simplifying GOTO. Drop the GOTO command's CMDLBL keyword.
5.0 Miscellaneous Suggestions
Several other general techniques can help make your CL programs more readable and maintainable. Here are some ideas:
5.1 Insert a blank after each opening parenthesis and before each closing parenthesis. This rule may seem trite, but it makes your code easier to read.
5.2 Develop a standard error-handling routine, and place it at the end of your code. It's wise to insulate your users from abnormal terminations. Toward that end, you should always include a standard error-handling routine in your programs. Use a global MONMSG statement to trap any unforeseen errors, and handle the errors gracefully in the error-handling section. Tuck this section of code out of the way, at the end of your code.
5.3 Extract single values from multivalue variables before referring to the values. When a variable contains more than one value, such as a qualified object name or the contents of a data structure, extract the individual values before using them in your program. Declare individual fields and then use the CHGVAR command with the %SST built-in function to extract the fields (E). Then use these individual fields in your program.
Start Stylin'
You can use the guidelines in this article as the foundation for a style that lets you write CL code that's easy to read, understand, and maintain. Try out these style suggestions, share your ideas about what works with others, and implement your own set of standards to give your CL more style.
Gary Guthrie is a NEWS/400 technical editor and editor of The RPG Source, a newsletter of practical tips and techniques for AS/400 developers. You can reach Gary by e-mail at gguthrie@news400.com.