A Style Guide For Modern RPG and ILE, Part 1

Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

THE FOUR HUNDRED SUBSCRIBE MEDIA KIT CONTRIBUTORS ABOUT US CONTACT

A Style Guide For Modern RPG And ILE, Part 1 Volume 16, Number 22 -- October 4, 2016

October 4, 2016 Paul Tuohy

THIS ISSUE SPONSORED BY:

WorksRight Software
One of the basic principles of programming is that coding conventions (guidelines and standards) improve
COMMON
the readability of source code and make software maintenance easier. Coding conventions provide the UCG Technologies
foundation for developing applications that are easy to maintain and modify. This article and an article to
follow are a style guide to coding RPG programs using free-form RPG in an ILE environment.

When developing guidelines and standards, one of the major challenges is to determine what is a standard
and what is a guideline. For example, code indentation would be a standard, but whether the code is
indented by two, three, or four characters would be a guideline. One of the objectives of standards is to
ensure that required coding standards are implemented without impeding the creativity of the programmer.

Just Another Programming Language

RPG has now achieved the distinction of being just another programming language. This means that many of
the style guidelines and standards that apply to other programming languages (Java, PHP, etc.) now apply to
RPG as well. If you are developing in a multi-language environment, try to apply consistent standards to all
languages. For example, if the guideline for PHP is to indent code by three characters, the guideline for
indenting in RPG should be the same. Having consistent standards across all languages makes it easier for
programmers to switch between languages.
Even if you are not developing in a multi-language environment, you can still learn from other languages.
For example, use /INCLUDE instead of /COPY and use all uppercase for named constants–these are
conventions that are common to most (if not all) programming languages.

Use the Right Tools

RDi (Rational Developer for i) can help with the implementation of standards. Learn to make use of
Automatic Indent, the Outline View, Content Assist, Templates and Snippets: they can all help automate
standards and styles.

RPG Is Free-Form

Modern RPG programs should contain only free-form code–they should not be a mixture of fixed-form
and/or extended factor-2 and/or free-form. Complete free-form means that a lot of old “bad habits” (MOVE,
MOVEL, GOTO, etc.) are no longer available. Coding only free-form code means that a programmer will not
accidentally fall back onto old habits and coding practices.

If a decision is made that existing programs are not going to be converted to free-form RPG, then any Table of Contents
modifications to the programs should be made in free-form only.
A Style Guide For Modern RPG And ILE, Part 1
Whether writing new programs or modifying existing programs, only code in free-form RPG. However, What’s In A Save File?
when modifying existing programs, avoid creating the situation where the code switches frequently Searching Source In The Twenty-First Century
between fixed-form and free-form code. If you are making small modifications to fixed-form code,
consider changing that section of fixed-form code to free-form before making your changes.

Modern RPG Programs and Subprocedures

A modern RPG program uses free-form syntax and is modular in structure. This modular structure is
implemented with subprocedures. Subprocedures may be coded internally in a module or they may be
external (in a service program or another bound module).

Although multiple subprocedures will be coded within a module, the approach to writing a subprocedure
should be that the subprocedure is standalone. This means that the design of a subprocedure is such that it
makes copious use of local variables as opposed to global variables, and that all required data that is external
to the subprocedure is passed as parameters and/or a return value. Simply put, think of every subprocedure
as a standalone program.

This approach to writing subprocedures means that when it is determined that a subprocedure may be
useful in other places, it is a simple process to remove it from its current module and place it into a service
program.
A subprocedure should be designed to perform one task (calculate_Pay(), get_customerData() etc.). It is OK if
the subprocedure has to call other subprocedures to achieve that single task. This, in turn, means that
subprocedures should be short and to the point. A good rule of thumb is to be able to see all the executable
code for a subprocedure in a single window in RDi.

Also, when you find yourself defining global variables, stop and ask yourself: Why?

Naming?

Before looking at the components of naming conventions, remember that although RPG is a mixed-case
language, it is not a case-sensitive language. This means that, in an RPG program, the variable names
customerID, CustomerID, customerid, and customerId all refer to the same variable, whereas in a PHP or
Java program they would be four different variables. However, you should strive to use the same mixed-case
form everywhere you use the name.

The Names

Names should be meaningful. The restriction of 10-character system names on IBM i has made RPG
programmers masters of abbreviation. It is a habit that needs to be broken. Names should be meaningful and
descriptive, and should not be restricted by a length (although perhaps you should avoid creating names up
to the maximum allowed length of 4096). Just as a name should not be overly abbreviated, it should not be
overly verbose. For example, the variable should be customerID, not cusID or theIDOfTheCustomer.

When naming variables, arrays and data structures, think of the name as a noun–it simply states what the
“item” is. For example, currentAccountNumber, customerID, or customerList.

When naming subroutines, subprocedures or prototype names, think of the name as a verb combined with a
noun. In other words, there is an action and an item. For example calculate_Pay(), get_customerData(), or
convert_toCelsius();.

Use consistent abbreviations in your names. For example, if you have several procedures that do the
“convert” action, be consistent in how you name the action (“convert”, “cvt”, “conv”, and so on).

Case

Names (with the exception of named constants) should be mixed case. The usual standard is to use
CamelCase. CamelCase means that a name is made up of compound words where each word begins with a Content archive
capital letter. The first word may start with a capital letter or with a lower case letter but all following words
would start with a capital letter. For example, CurrentAccountNumber or currentAccountNumber. The Four Hundred
Four Hundred Stuff
But, since RPG is not case sensitive, it is up to the programmer to follow the guideline. Four Hundred Guru
Special Characters

With the exception of the underscore character, special characters (i.e., @, #, $) should not be used in names.
Some of the special characters are prone to change dependent on CCSID definitions and should be avoided.

Underscore

The underscore character can be used to add clarity to a name. There is an inclination to use underscore to
separate compound words in a name, but this is usually superfluous when CamelCase is being used. The
name currentAccountNumber is just as legible as current_Account_Number.

But underscore can be useful when used with subroutine, subprocedure or prototype names. The
underscore is used to separate the action from the item: calculate_Pay() or get_customerData().

Given the following line of code:

salary = calculatePay(97);

A programmer would need to check whether salary was being set by a call to the subprocedure
calculatePay() or from element 97 of the array calculatePay. The use of underscore in subprocedure names
would add clarity to the code.

salary = calculate_Pay(97);

An underscore is also used to separate the words in a named constant (if your standard is to use all
uppercase for named constants).

Named Constants

Use named constants instead of literals. Constant names make code self-documenting and easier to
maintain. The exception to this is the use of 0 and 1 in expressions when clearing, incrementing, and
decrementing field values. A constant name should reflect the function of that constant, not the value.

The convention in most programming languages is that constant names are all uppercase. Accordingly,
underscore should be used to separate compound words within the name.

Compare the use of a literal:


if (%status(myFile) = 1218);

With the use of a named constant:

if (%status(myFile) = ERR_RECORD_LOCKED);

If literals are standard throughout an application (i.e., status codes), the named constants should be defined
in a copy member and included in programs as required.

Naming Conventions

With the proviso that names should be meaningful, naming conventions can be used to identify a usage or
grouping of variables or named constants. The convention is that the correlated names start with the same
characters followed by an underscore.

For example, a copy member includes the following named constants used to identify message IDs. All of the
named constants begin with MSGID_.

dcl-C MSGID_CODE 'ERR0001';


dcl-C MSGID_DESCRIPTION 'ERR0002';

Use a standard prefix or suffix to distinguish template variables and files. For example, use a prefix such as
type_, or typ_, or t_, or use a suffix such as _T, or _typ, or _type.

In the rare occasion when global variables are used in subprocedures, the names of the global variables
begin with the characters g_.

When naming subprocedures and prototyped program calls, it is imperative that the naming convention is
consistent. For example, subprocedures that add information to a database should start with add_ or write_,
not a mixture of the two.

Naming conventions are definitely required for names that are defined through copy members or globally
defined in a program/module. But the use of local variables (in subprocedures) and qualified data structures
minimizes the requirement for naming conventions within subprocedures.

Comments
All programs need to be documented. One of the major benefits of free-form RPG and proper naming
conventions is that it reduces the need for detailed documentation because the code is self-explanatory.
Even so, programs need to be documented.

Comments should be used in two ways in RPG programs and subprocedures:

1. Summary for a program, subprocedure or section of code


2. Detailed commenting of certain code

Summary Comments

Summary comments should be at the start of every program and subprocedure. Summary comments should
contain, at least, the following information:

The title of the program/subprocedure


A description of what the program/subprocedure does
The name of the author
History of changes made to the program

Detailed Commenting

One of the major benefits of free-form RPG and proper naming conventions is that it reduces the
requirement for detailed commenting. Detailed commenting should only be required to explain some
complex coding technique or to highlight a technique being used in the code.

Other Commenting

Use blank lines to group and segment code.

It can be useful to use a marker line comment to separate major sections of a program, although the
requirement for this is somewhat nullified when using the Filter View feature in RDi.
Positions 1 to 5

Historically, positions 1 to 5 may have been used to indicate or flag lines that were changed for a certain
modification. This practice should be avoided. Specifying **FREE on the first line of code means that
positions 1 to 7 on all subsequent lines may be used for code.

Structuring Code

All code should be structured. The standards and guidelines for declarative code and executable code will be
slightly different.

Declarative Code

Declarative code is defined at the start of a module, program, or subprocedure. Definitions should be
grouped together by type of declaration.

Declarations should be grouped so that related items are defined together. The procedure interface should
be first, before any other declarations.
Indentation should be used with data structured to identify overlaying structures.

Align definitions so they are easy to read. For example, when defining stand-alone variables, parameters or
data structure subfields, align the data type on each line. Compare the definition of this data structure with
alignment.

dcl-Ds APIError qualified;


bytesprovided int(10) inz(%size(APIError));
bytesavail int(10) inz(0);
msgid char(7);
*N char(1);
msgdata char(240);
end-Ds;

To one without alignment:

dcl-Ds APIError qualified;


bytesprovided int(10) inz(%size(APIError));
bytesavail int(10) inz(0);
msgid char(7);
*N char(1);
msgdata char(240);
end-Ds;

Executable Code

All executable code should be indented. Indentation within loops and groups adds to the legibility of the
code.

if (messageCount() = 0) ;
select;
when CGIOption = 'CANCEL';

when CGIOption = 'DELETE';


failed = delete_Event(persistId);
other;
set_eventData(persistId : data);
if (messageCount() = 0);
failed = put_Event(persistId);
endif;
endSl;
endIf;

If a statement takes more than one line of code, use alignment to make the code more legible.

set_days_for_Event(data.event:
%date(data.fromdate: *USA):
%date(data.todate: *USA):
%date(data.wrkshpdate: *USA));

Automatic indent (and closure of control block) can be set in the ILE RPG preferences for the Remote
Systems LPEX Editor in RDi.
Multipath Comparison

Deeply nested IF/ELSE/ENDIF code blocks are hard to read and result in an unwieldy accumulation of
ENDIFs at the end of the group. Instead use the more versatile SELECT/WHEN/OTHER/ENDSL or the
IF/ELSEIF/ENDIF constructions.

Use SELECT/WHEN if the choice statements all compare a particular variable to a set of values. Use
IF/ELSEIF if the choice statements have varied types of conditions.

Embedded SQL

Use indentation and alignment to make SQL statement legible. An SQL formatter is available in Run SQL
Scripts in IBM i Access Clients Solutions.

exec sql
declare C001 scroll cursor for
select event, daynum, agendaid, fromtime, totime, showseq, title
from AGENDA
where event = :eventIn
order by event, daynum, showseq, agendaid
for read only;

Use Templates and Qualified Data Structures

Templates and qualified data structures provide a means of clearly defining and documenting data items in a
program.

A qualified data structure means that all references to the data structure subfields must be qualified with the
data structure name, fors instance, mailAddress.city, mailAddress.state. This allows for subfields with the
same name to be defined in multiple data structures without the possibility of conflict and so that the
association between a subfield and its data structure is clear.

Defining a qualified data structure as a template means that the data structure may not be used as a data
structure but can be used as the template for other data structures that are defined using the LIKEDS
keyword. In the following example, a reference to the subfield baseAddress.city would be invalid but a
reference to the subfield mailAddress.city would be valid.

dcl-Ds baseAddress template qualified;


street1 char(30);
street2 char(30);
city varchar(20);
state char(2) inz('MN');
zip char(5);
zipplus char(4);
end-Ds;

dcl-Ds mailAddress likeds(baseAddress) inz(*likeDS);

Templates and qualified data structures provide an excellent means of gathering together related “work”
variables in a program or providing parameters for a call interface. The definition of the template data
structure can be placed in the same copy member as the prototype definition for a called program or
subprocedure.

The LIKEREC keyword can also be used to define qualified data structures based on input/output records for
an externally described file.

You can also define template fields (with the LIKE keyword) and files (with the LIKEFILE keyword).

Qualify Wherever Possible

When using built in functions such as %EOF(),%FOUND(),%EQUAL() and %STATUS(), always provide the
associated file name as a parameter.

Unfortunately, the %ERROR() built in function does not allow for a file name parameter, so always check the
%ERROR() function (or the %STATUS() function) directly after an operation with an error (E) extender. Or
save the setting to a variable so that you can test it later.

Strings

The more that you program for the web, the more you work with strings.

When it comes to string handling, it is better to use varying length (VARCHAR) as opposed to character
(CHAR) fields. The use of varying length fields reduces the requirement for string functions (%TRIM etc.) and
makes the code more legible.

Subroutines

Subroutines should not be used for modularization/structure. Subprocedures should be used instead. But
subroutines can be useful in organizing the logic in a subprocedure.

To Be Continued

The rest of the guidelines will be in part 2!


Paul Tuohy is CEO of ComCon, an iSeries consulting company, and is one of the co-founders of System i
Developer, which hosts the RPG & DB2 Summit conferences. He is an award-winning speaker who also
speaks regularly at COMMON conferences, and is the author of “Re-engineering RPG Legacy Applications,”
“The Programmers Guide to iSeries Navigator,” and the self-study course called “iSeries Navigator for
Programmers.” Send your questions or comments for Paul to Ted Holt via the IT Jungle Contact page.

Tags:

Sponsored by
Briteskies

From RPG development, technical consulting services, and EDI solutions, to eCommerce
integration and security audits, Briteskies can handle it all. As a full-service consulting
company, we have IBM i experts in place to help you on a short-term project basis or long-
term assignment.

Read our blog for more information about our expertise. Check out our Customer Success
Stories to see how we help companies improve their efficiency.

Learn more at www.briteskies.com or Contact Us Now to see how we can help keep your
business running.

Sponsored Links

BCD: Webinar: Rapid Node.js Web and Mobile Development with WebSmart. Oct. 6 at 1pm ET.
Fresche: IBM i staffing for all of your IT needs. Request a FREE estimate. 1-800-361-6782
Manta Technologies Inc.: The Leader in IBM i Education! Download catalog and take sample
sessions!

Two Fall Conferences Are Must- IBM i Tech Refresh Arrives; JSON
See IT And Perl In Spotlight
One thought on “A Style Guide For Modern RPG And ILE, Part 1”
TC Diep says: April 7, 2018 at 7:51 am

Hi

Thanks for the great article. One question if I may. “Even if you are not developing in a multi-
language environment, you can still learn from other languages. For example, use /INCLUDE
instead of /COPY…” I’ve been trying to find out the difference, and it appears to be how the SQL
precompiler handles the instruction. Am I right to say /INCLUDE won’t accept embedded SQL in
the source to be copied/included?
So that sounds like a serious limitation to /INCLUDE. How would you get around it?

Reply

Leave a Reply

Recent Posts Subscribe


AWS Inks Deal With Connectria To To get news from IT Jungle sent to
Have a Power Play your inbox every week, subscribe
IBM i Shops Have Alternatives to to our newsletter.
Db2 Web Query
Eradani Lays Waste to API Payload
Restrictions
Four Hundred Monitor, November
15
Old PHP and Other PASE Apps
Break on IBM i 7.5 Pages Search
New GM Wants To Push IBM
Power With Hybrid Cloud And AI About Us
IBM Finally Comments On Db2 Contact
Web Query For i Withdrawal Contributors
IBM To Add Generative AI To Four Hundred Monitor
QRadar IBM i PTF Guide
IDC Boosts IT Spending Forecasts Media Kit
For 2023 And Beyond Subscribe
IBM i PTF Guide, Volume 25,
Number 46

Copyright © 2023 IT Jungle

You might also like