Subprocedure Names

The most important factor in assigning a name to a subprocedure is, selecting the name. At first, that statement seems childishly obvious, but as I'll show, it is useful to establish and use a strong convention and pattern when assigning a name.

Many RPG programmers are accustomed to creating names based on simple requirements. If you haven't been routinely coding subprocedures, the nearest equivalent you have in RPG is subroutine names. Subroutine names are not a good pattern to use for subprocedure names for these reasons:

Without implying any cheap vulgarity, I believe it is the case that with subprocedure names, longer is better. I will show this in following sections with several examples.

System/38 syndrome

An affliction commonly suffered by RPG programmers is what I term "System/38 syndrome", that is, the overwhelming tendency to reduce all names to the 3-letter verb/object convention popularized by CPF, the predecessor of OS/400. To be sure, when the convention was first introduced, it was a radical and welcome break from earlier operating system naming conventions, as it allowed seemingly limitless combinations of objects and actions. When working within the confines of a 10 character long name space, there is merit in adopting the convention.

However, ILE RPG supports names longer than 10 characters. There is little reason to perpetuate a stilted naming convention that is no longer required. I would no more feel compelled to use operating system command naming conventions for my subprocedure names, than I would feel it necessary to use truncated variable names. The only place where we are still routinely constrained to 10 character names is in D-spec file fields. Apart from that, I don't consider length to be an issue when creating a name for a subprocedure or variable.

So how long can it be?

The maximum length of what the RPG documentation writers call a "symbolic name" is probably far greater than you imagine: 4096. You can look this up in Appendix A, "ILE RPG Restrictions" of the ILE RPG Reference. Needless to say, this is an unusably long name length, unless your intent is program obfuscation. (Although I feel that most RPG programs are already sufficiently obfuscated, without needing to resort to excesses in field naming.)

Obviously, the ideal subprocedure name length is much less than 4096. However, the right length for a particular subprocedure name may well be more than 14 characters, the maximum allowed in the name columns on a D-spec.

D-spec continuations

It turns out that the D-spec 14 character limit is an artificial limit that is easily busted. You can create a longer subprocedure name by the simple expedient of appending an ellipses ("three dots") at the end of the subprocedure name:

D MESSAGES_getLabel...
D                 pr

The syntax is trivially simple and takes almost no time to get used to. The problem is that the source code editors (SEU, CODE/400 and WDSC) may squawk at the apparent error. Just ignore the editors and proceed on to the next D-spec, where you define the characteristics of the subprocedure or field you are defining.

One of the great benefits of using the D-spec continuation is that you no longer need to constantly adjust the column sensitive values that describe the name. It is not unusual while developing a module to change subprocedure names. Using the continuation specs, you can easily add or remove characters without any need to adjust other entries.

I routinely use D-spec continuations for all definitions, even when the name fits within the 14 character limitation. Rather than look at a crowded mass of field definitions, I now have specifications that have some space, some breathing room, built in. Data, variables and work fields are the actors that perform within your programs. Each should be properly introduced and made to be easily recognizable and visible. By taking some time and care to make your D-spec definitions easy to use, you don't need to spend as much time looking for field definitions in cross reference listings.

Subprocedure names rule #1

The first rule of subprocedure names is so obvious that I am (1) surprised that it has not been more frequently posited as a rule, and (2) astonished that it has been overlooked as the solution to one of the biggest problems of subprocedure naming.

When you create a subprocedure that is intended for use by external clients (that is, it is exported and can be called by subprocedures in other modules), you need to assign a name that will not conflict with other names that are known by the external client. For example, if I create a subprocedure named CalcDateDue in two different modules, I am certain to have problems if I bind the two modules in another object. One way or another, I have to indicate which of the two subprocedures I intend to use.

There is a way to resolve this duplicate name problem using the "create" commands, to force a preference for one module's exported name over another. I am completely uninterested in the rules for this type of duplicate name resolution, and will not attempt to describe here how to solve an unnecessary problem.

The ironclad rule that I have adopted to avoid subprocedure name collisions is: for a subprocedure that is exported from a module, the module name is appended as a prefix to the name. For example:

D MESSAGES_getLabel...
D                 pr

not

D getLabel...
D                 pr

By using the module name MESSAGES as the prefix, it is immediately obvious which module contains the subprocedure. If you need to look at the code for the subprocedure, its documentation or other facts about the module that it's in, you'll know right away where to start looking.

Another important reason to use the module name prefix technique is that it helps you form a mental model of the module(!). When you see the module name used as a prefix for several subprocedures, you'll more clearly recall other features of the module and the overall functionality of the module.

If you haven't worked much with exported subprocedures in your programs, you might be skeptical about my insistence upon this naming convention. If your experience is primarily with subroutines in programs, then you have not really been exposed to the issue, as subroutines are, by definition, internal to the program. They can only be located in one place, that is, within the program. If you are going to start serious work with modules that export subprocedures, you'll soon have many modules and dozens or hundreds of subprocedures. At that point, you'd better have a workable naming convention for your exported subprocedures, or you'll need to be prepared to spend a lot of time tracking down subprocedure code and dealing with cross module duplicate names.

The application of subprocedure names rule #1 leads directly to rule #2.

Subprocedure names rule #2

The second rule of subprocedure names is the mirror image of rule #1. That is, for subprocedures that are defined in a module but are not exported from the module, the name should not start with the module name. It is unnecessary to use the module name, as the subprocedure by definition can only be called within the module. By omitting the module name prefix, you help to clarify the subprocedures that are meant for export, and those that are not.

This rule raises a question. Why would a module contain subprocedures that are not exported? It turns out that you will frequently want to split code in your modules into smaller sections. You can freely create as many internal use subprocedures as needed to perform "worker" tasks to service the exported subprocedures.

Now look at the code shown above for rule #1 and apply both rules.  It is obvious that the first definition defines a procedure that will be exported from the module. This procedure can be called by external clients of the module:

D MESSAGES_getLabel...
D                 pr

Similarly, by applying rule #2, this procedure is intended for internal use only. This subprocedure is called from MESSAGES_getLabel to handle the actual work of getting a label:

D getLabel...
D                 pr

In later articles, I'll go into more detail about the relationship of the exported subprocedure to its associated worker. In many cases, unless the job of the exported subprocedure is trivial, I have the exported subprocedure call its worker. The exported subprocedure is primarily responsible for validating parameter values, setting defaults, calling the worker, and conveying the result back to the original caller.

Subprocedure names rule #3

The third rule for a subprocedure name is that it is spelled out. For exported subprocedure names, the module name will typically be from 6 to 10 characters long, so you'll be busting the 14 character D-spec limit when you use the module name as a prefix. With the name continuation technique shown above, you can easily type a longer name. Since you have the space, there is little reason not to spell out the parts of the subprocedure name.

For example, rather than

D MESSAGES_getLbl...
D                 pr

use

D MESSAGES_getLabel...
D                 pr

There is no reason to prefer the System/38 convention and try to shoehorn nouns and verbs into 3 letter abbreviations. If you stick with that convention, you'll inevitably have some conflict where the same 3 letter code could stand for more than one word. The weak excuse of using short names so you won't have to type as much loses appeal once you start seriously using subprocedures. You're no longer limited to command-style names, so you might as well start thinking more expansively about your code, beginning with subprocedure names.

Subprocedure names rule #4

The fourth rule might strike you as being overly restrictive for no good reason, but I recommend that you adopt this rule from the very first. Simply put, the verbs "get" and "set" as part of the subprocedure name (as in MESSAGES_getLabel and MESSAGES_setLabel) are reserved for a special type of subprocedure called an accessor. I will show you how to create and use accessor subprocedures in later articles, as accessors are one of the main tools you use to construct modules.

By reserving "get" and "set" for accessors, you'll be able to easily create modules with accessors, other publicly available subprocedures and clearly defined internal subprocedures.

Subprocedure names rule #5

The last rule might seem to be pointless hectoring, but I will not apologize for it: type the name the same, every time you use it. Consider it to be case sensitive. The initial definition in the D-spec prototype is the canonical (definitive) form of its name.

For example, don't litter your code with variations of a subprocedure name like this:

MESSAGES_getLabel

Messages_getlabel

Messages_GetLabel

messages_getlabel

Instead, go back to the D-spec, find the name as defined, and use that. If you decide you don't like the name or its form, change it on the D-spec, then change it in all other locations. (By the way, don't type a subprocedure name using all uppercase letters, as names that are all uppercase are reserved for constants. This will be discussed in a later article.)

The reason for this rule is that it forces you to pay attention to your code. Most code in older RPG programs was always written in uppercase, so there wasn't much of a consistency issue in the old days. Over the last 10 years or so of RPG code writing, most programmers have started to use lowercase in their code. In many cases, there is no discernable pattern to the use of uppercase or lowercase.

Many other programming languages that you might work with are case sensitive. If you start treating RPG as if it too were case sensitive, you'll find it much easier to adapt to other languages as needed. Even if you don't plan to use anything but RPG, you'll still benefit by treating names as if they are important. When you read an RPG program that you didn't write, you form many impressions and opinions about the quality of the code and the degree of trust that you have in the code. If the programmer has obviously put thought into their expression of the code, it is easier to accept other aspects of their code which might not be familiar to you. When I read an RPG program where there is no consistency in the use of names, where comments are riddled with typos and no effort is made to indicate logical structure, I find it very difficult to grant a level of trust to the programmer.

So much for so little?

You might feel somewhat put off by these rules. After all, if you've been programming for any time, you've been making up names for hundreds of program artifacts. But I will again call to your attention, subprocedure names, especially for exported subprocedures. are unlike any other RPG names. By design, subprocedures will be used by potentially many different callers. If you create good, strong names at the outset, you'll find it much easier to use your modules than if you use constrained names, coded as if they weren't really meant to be used in the outside world.

Craig Pelkie
October 15, 2004