Midrange News for the IBM i Community

3 Primitive Coding Practices to Avoid in RPG IV Published by: Bob Cozzi on 17 May 2011 view comments
© 2011 Robert Cozzi, Jr. All rights reserved.

© Robert Cozzi, Jr. All rights reserved. Reproduction/Redistribution prohibited.
A midrangeNews.com Publication

3 Primitive Coding Practices to Avoid in RPG IV

Legacy Holdout

You know him (or her) don't you? Your Programming Manager or that Senior/Lead RPG Developer whose techniques learned before the "dot com" bubble, before the first President Bush, are being sold as "modern" RPG. As the guy who literally wrote the book on "The Modern RPG Language" I can tell you that programming practices, like so many other things, don't last forever.

I've said it before, simply because "in my day, we did it this way" does not mean its valid today. To that point, I want to illustrate 3 deprecated techniques (in keeping with the theme of this article, the word "deprecated" is the modern way to say "obsolete" ) and show the contemporary techniques used in place of them 

Sponsored by: Valence

Faster Horses, Again?

A few weeks ago, I wrote a blog post entitled "We wanted faster horses" (available here).  Among other things I discussed how we try to hang onto the past more than we try to improve ourselves--almost to a point where as IT Professionals we effectively devalue ourselves professionally. The past is important for learning and remembering, but we need to evolve our skills or risk losing the advantage that we bring to our employer.

Three Deprecated RPG Techniques

There have been many legacy RPG techniques that we've given up as these last 15+ years of RPG IV have replaced the old RPGIII language. We no longer use the RPG logic cycle, Primary and Secondary Files are virtually non-existent, the use of short variable names has been relegated to work-fields, and indicators are virtually never used in new code.

Several long-since retired features of RPG seems to crop up in code from time to time--some of it so archaic that younger RPG developers often know know what's going on in the code. Here's my list of the top 3 features of RPG that should never be used again, are you guilty of using some of these and adding to the "AS/400 is old technology" myth?

  1. Multiple Occurrence Data Structures
  2. Subroutines
  3. From/To Column Notation

Data Structures

With the introduction of IBM i version 5, IBM added Qualified Data Structure support to RPG IV and changed everything. This single feature is my Top RPG IV Feature of all time. More than free-format, Qualified Data Structures have set RPG developers free by no longer require terse, archaic variable naming just to avoid conflict/name collisions.

Along with Qualified Data Structure came Data Structure Arrays. The DIM keyword can be used to set the number of array elements for the data structure. This deprecated the 35+ year-old OCCURS feature known as Multiple Occurrence Data Structures.

Multiple Occurrence Data Structures use the OCCURS keyword to set the occurrence count, and the OCCUR opcode or %OCCUR built-in function to access individual occurrences. This technique works fine in fixed-format where 10 or 14 position Factor 1 and 2 limitations were in place. But in free-format or hybrid RPG IV, it just seems wrong.

Data Structure Arrays allow a data structure to be treated just like an array with additional features. That is, you can actually sort a data structure array by one of the data structure subfields--a fantastic feature, or search it by a subfield.

The other advantage is intuitive, I think. You can use the data structure array in the Calc's using array subscript notation. For example, instead of doing this archaic technique:

.....D LINEITEM        DS                  OCCURS(100) 
     D   ITEMNO                       5A
     D   QTYORD                       5P 0
     D   ITMPRC                       7P 2
           X = 0;
           DOW (X < %OCCUR(lineItem)) ;
               X += 1;
               %occur(lineItem) = X;
               if (itemNo = '');
               if (qtyOrd <> 0);
                  exsr addToCart;

...a better choice is to do this:

.....D lineItem        DS                  Dim(100) Qualified  INZ
     D   itemNo                       5A
     D   qtyord                       5P 0
     D   price                        7P 2
           X = 0;
           for X = 1 to %dim(lineItem);
               if (lineItem(x).itemNo = '');
               if (lineItem(x).qtyOrd <> 0);

Granted I tried to make both examples as contemporary as possible, but lets look at the differences:

The Qualified Data Structure array uses the DIM and QUALIFIED keywords. In addition, my "RPG IV Course: Day 1, Hour 1, Rule 1" is "Always Initialize Your Data Structures". As I've said time and time again, people have code that has been blowing up for years, and 99.9% of the time its because the legacy RPG program refuses to consider using the INZ keyword. Here's what I tell people:

"If you declare a data structure, the declaration is NOT complete unless you add the QUALIFIED and INZ keywords to the definition."

As an overly hasty generalization, anyone who puts a program into production without specifying the INZ keyword on their new data structures, should be fired; no exceptions. Why? Because it shows that they have no idea how to write RPG IV and are faking it.

(Disclaimer: The above is a <rant> and not legal advice to any company, person or organization.)

Bottom Line: Data Structure Arrays are cool, use them where ever a Multiple Occurrence Data Structure was used.

Subroutine Smugroutines

A noted scientist was asked to respond to people who don't believe in Global Warming, the age of the Earth and other things. His response, I think, also applies to those who don't believe RPG SubProcedures are better than RPGII Subroutines. He said "That's the thing about Science, it's still true whether you believe it or not."

I've been tough on some developers over the years, and hurt some people's feelings with my blunt nature--as a result, my advice has often fallen on deaf ears. But if IBM had done Subprocedures from the beginning, there would be no reason to ever consider adding Subroutine support to RPG IV. In other words, Subprocedures do everything Subroutines could do, and much, much more.

The only advantage Subroutine use has today, is typing habits. Heads-down coders, and the long-time-since-I've-written-a-production-app IT Manager tend to use Subroutines instead of Subprocedures simply because they can type "exsr mysubr" faster than defining a subprocedure and writing "myproc". I don't understand that thinking, but it is something we all live with. Sure there's some kludgie syntax involved in subprocedure coding, but hey this is RPG, we invented kludgie syntax.

Here's the implementation of a Subroutine:

         begsr AddToCart;
             ci +=1;
             %occur(cart) = ci;
             cItem = itemNo;
             cQty  = qtyOrd;
             cPrice= itmprc;

Here's the body of a Subprocedure that accomplishes a similar task:

     P addToCart       B
     D addToCart       PI
     D  item                               Const LikeDS(lineItem)
     D  line           S             10I 0 Static
             line +=1;
             eval-corr cart(line) = item;
     P addToCart       E  

An RPG feature added in IBM i v6r1, allows you to avoid defining a Prototype for subprocedures that are NOT called from outside of their implementation source member (i.e., they are effectively used like a legacy subroutine). This avoids a ton of confusion and unneeded extra coding and removes the single excuse for avoiding Subprocedures, which was "they're too verbose to write".

Here's a short list of advantages the RPG IV Subprocedure feature has over the legacy Subroutine feature from RPGII

  • Local Variables (avoids work-field naming conflicts)
  • Pass Parameters (avoid excessive work fields)
  • Return Value (allows them to be used with IF/WHEN/DOW/DOU statements)
  • Shareable (can be exported and reused at the object code-level)
  • Automatic Storage Variables (fresh variables on each call to the subprocedure)
  • Static Storage Variables (variables that retain their value between calls to the subprocedure)

If you still believe subroutines are better than subprocedures, it doesn't matter; Subprocedures are better, get over it.

From/To Column Notation

When 80-column punched cards were developed, they were a revolution. But because of their limited capacity (80 characters) the RPG language was designed to work with those cards. So was COBOL but RPG had much more ridged fixed-format syntax than COBOL statement boundary. When we moved to RPG IV, IBM made a conscious decision to retain some legacy capabilities for two reasons:

  1. It made the program that converted RPGIII to RPG IV easier to write.
  2. It made it easier for the RPGII and RPGIII Programmer to read RPG IV intuitively.

When they implemented the Definition Specification or "D spec" as we call it, they incorporated the legacy from/to column notation of the RPGII Input Specifications. However, they also deprecated that capability by including length-notation. By simply specifying the length of the field or subfield instead of from/to columns, you declared a field of the size you need instead of "adding 1 to the length, dividing it by 2, then calculating the start position from the previous field". Here's a great example using the INFDS:

     DCOLOR                    1     10
     DDIAMETER                11     12P 0
     DWEIGHT                  13     15P 0
     DQTY                     15     18P 0

There are so many things deprecated in this legacy style that I don't know where to begin. Yet, it is still widely used.

First, the data structure is NOT initialized. This is a huge failure on the RPG developer's part. Packed subfields and the DS isn't initialized? Are we so lazy we can't type 3 extra characters?

Next, the data structure should be migrated to a Qualified DS, although not strictly necessary depending on the context.

Finally, the field name "case" is all caps. RPG IV should use mixed case, or if you prefer, all lowercase letters for variable names. "ALL CAPS" is always a bad idea.

 Migrating this to RPG IV syntax (and yes it is technical RPG IV syntax already, but it is really an RPGII/RPGIII structure) is a matter of converting the from/to column notation to length-notation.

I've done this to this data structure, below. I have also included other things I felt were missing from the original data structure.

         // Contemporary Syntax
.....D appleSauce      DS                   Qualified Inz
     D   color                       10A
     D   diameter                     3P 0
     D   weight                       5P 0
     D   quantity                     7P 0

This data structure gets an A+. It is qualified, initialized, and its subfields are in mixed (mostly lower) case letters. It also has the subfield names indented a bit help illustrate their hierarchy within the data structure.

But look at the field definitions themselves. Using length notation, I can specify a 7-position packed field with zero decimal positions as "7P 0" instead of "1     4P 0". I also don't have to calculate the subfield locations.

If however, I want to use absolution positioning in the data structure for a subfield, I can add the OVERLAY keyword, as follows:

         // Contemporary Syntax
.....D appleSauce      DS                   Qualified Inz
     D   color                       10A
     D   diameter                     3P 0
     D   weight                       5P 0
     D   quantity                     7P 0
     D  ItemNo                        8A
     D   category                     2A    Overlay(ItemNo:1)
     D   seqnbr                       3S 0  Overlay(ItemNo:*NEXT)
     D   REV                          3S 0  Overlay(ItemNo:*NEXT)

Note the 4 new lines I added to the bottom of the data structure. The ITEMNO subfield is overlaid with 3 additional subfields. The OVERLAY keyword allows me to use length-notation, but also position these other subfields using absolution positioning. Actually only the CATEGORY subfield is positions absolutely, and the SEQNBR and REV subfields are positioned relative it CATEGORY. Pretty cool, huh?

More Garbage

Just for grins, I thought I'd list a few other bad habits I occasionally see in shops where I am asked to do training or consulting:

  1. Using "SELECT * FROM..." in SQL instead of listing specific field names.
  2. Using # @ $ in variable or subprocedure names instead of valid, readable names.
  3. Not specifying the data-type for fields or subfields (especially numeric fields).
  4. Not using INZ on a Data Structure declaration statement--this is just stupid not so much a bad habit.

If you're still doing item 1, I might giggle at you a bit. If you're doing item 2, I'll think less of you, and if you're doing item 3 or 4, I might revoke your RPG Programmer's license.


You're welcome!

Call Me

Bob Cozzi is available for on-site RPG IV and SQL training, as well as consulting. Currently many shops are asking Cozzi to join them for 1 or 2 days of Q&A with their RPG staff. The Staff gets to ask real-world questions that apply to their unique situations. Leave a note on the feedback if your interested in having Cozzi at your location, or send him an email at: bob at rpgworld.com

Bob also accepts your questions for use in future RPG Report articles or content for midrangeNews.com. Topics of interest include: RPG IV, Web development with RPG IV, APIs, C/C++ or anything else IBM i development related (except subfiles, data areas and RPGII/III because Bob doesn't care about that stuff) write your questions using the Feedback link on the midrangeNews.com website. 

You can subscribe to RPG Report (we call it "follow") by visiting the RPG Report page on midrangeNews.com and then click the FOLLOW link in the table of contents for that page. To unsubscribe, simply click that same link. You must be signed up and signed in to midrangeNews.com to start following RPG Report.

Follow Bob Cozzi on Twitter

Return to midrangenews.com home page.
Sort Ascend | Descend