RPG Programming Style Standards - Write Code That Others (and Future You) Will Thank You For

Write Code That Others (and Future You) Will Thank You For

Few technical subjects stir stronger passions than programming standards. Some shops want almost none, others want a rule for everything. The truth is that good standards are shop-specific. They should fit your organization, your team, and the type of applications you maintain.

In this lesson I give you a practical, battle-tested set of RPG IV style guidelines. These are the ones I recommend you adopt (or adapt) so your code stays readable, maintainable, and professional. I promise to keep the list short enough that everyone can remember it and only focus on the important things.

Comments – Less Is More

Good comments explain why something exists, not what the code is doing. If your code is clear, you need fewer comments.

Best Practices for Comments

  • Always include a brief prologue at the top of every program and every subprocedure.
  • The prologue should contain:
    • Program or procedure title
    • Short description of purpose
    • Change history (date, programmer, reason for change)
    • Summary of indicator usage (if any)
    • Procedure interface description (return value and parameters)
    • Example of how to call the procedure
  • Use consistent marker lines (dashes or asterisks) to separate major sections: declarations, main procedure, subroutines, and subprocedures.
  • Use single blank lines to group related lines of code. Do not use multiple consecutive blank lines.
  • Never put right-hand “end-of-line” comments in columns 81-100 in legacy column-based RPG. If a line needs a comment, give it its own comment line above or below.

Example of a clean prologue

**free
/// ------------------------------------------------------------------------------
///
/// Program: PROGNAME - Brief Program Title
///
/// Description: Comprehensive explanation of the program's purpose and
/// functionality. Use multiple lines as needed with proper
/// indentation for readability.
///
/// Purpose: Educational/Production utility demonstrating:
/// - SQL embedded in RPG for data access
/// - Key concept or pattern #1
/// - Key concept or pattern #2
/// - Additional concepts as needed
///
/// Features:
/// - SQL cursor operations for efficient data retrieval
/// - Specific capability #1
/// - Specific capability #2
/// - Design pattern or best practice demonstrated
/// - Performance considerations
///
/// Control Options:
/// - main(mainline): Eliminates RPG cycle overhead
/// - optimize(*full): Maximum optimization
/// - option(*nodebugio:*srcstmt:*nounref): Debug and compile options
/// - pgminfo(*pcml:*module): Embeds parameter metadata
/// - actgrp(*new/*caller): Activation group strategy
/// - indent('| '): Code indentation character
/// - alwnull(*usrctl): Allow null-capable fields
///
/// SQL Options:
/// - commit(*none): No commitment control
/// - closqlcsr(*endmod): Close cursors at module end
///
/// Usage: CALL PROGNAME or detailed usage instructions
///
/// Parameters (if applicable):
/// - parm1: type - Description of parameter
/// - parm2: type - Description of parameter
///
/// Dependencies:
/// - Database tables or views accessed
/// - Required files, service programs, or APIs
/// - External resources needed
///
/// Copybooks Required:
/// - header.rpgleinc: Standard control options
/// - Other includes as needed
///
/// Reference:
/// https://www.nicklitten.com/relevant-blog-post-url
///
/// Modification History:
/// V.000 YYYY-MM-DD | Nick Litten | Initial creation
///
/// ------------------------------------------------------------------------------

Declarations - Keep Everything in D-Specs

RPG IV finally gave us a proper place to declare everything.

  • Declare all variables, constants, and data structures in D-specs (or free-form dcl- statements).
  • Do not declare variables in C-specs except for key lists and parameter lists (and even those belong at the top).
  • Whenever a literal has meaning, make it a named constant.
  • Indent data item names inside data structures to improve readability.
  • Prefer length notation over positional notation in data structures.
  • Use the OVERLAY keyword instead of positional notation when fields overlap.
  • For compile-time arrays, always use the **CTDATA form.

For example:

dcl-ds ErrMsgDS qualified;
  Prefix char(3); 
  MsgID char(4);
  Major char(2) overlay(MsgID:1);
  Minor char(2) overlay(MsgID:3);
end-ds;

Naming Conventions

The single most important part of style is the names you choose.

  • Make every name fully descriptive and unambiguous.
  • Use mixed case to make names readable (e.g., CustomerNumber, CalcTax).
  • Use verb/object naming for subroutines and procedures (e.g., LoadCustomer, ValidateOrder).
  • Avoid special characters (@ # $ _) whenever possible.
  • Keep names 10 to 14 characters long in most cases. Longer is acceptable in fully free-form source.

Indicators - Use Them Sparingly

Indicators are a legacy feature. Modern RPG can live with very few of them.

  • Eliminate indicators wherever possible.
  • Prefer built-in functions: %EOF, %FOUND, %ERROR, %EQUAL, etc.
  • If you must use indicators, give them meaningful names using an INDDS data structure or the array-overlay technique.
  • Never use conditioning indicators (columns 7-11) on calculation lines. Use IF, SELECT, or FOR instead.
  • Document any indicator you do use, especially U1-U8 or those sent to display/printer files.

Structured Programming Techniques

Always write structured code.

  • Never use GOTO, CABxx, or COMP.
  • Use IF / ELSE / ENDIF, SELECT / WHEN / OTHER / ENDSL, and DO / DOU / DOW / FOR.
  • Always qualify the ending opcode: ENDIF, ENDDO, ENDSL.
  • Use ITER and LEAVE for loop control instead of tricks.
  • Avoid obscure “bit-twiddling” opcodes unless there is no better alternative.

Modular Programming Techniques

ILE RPG and the Integrated Language Environment encourage modularity.

  • Always prototype every called procedure or program (dcl-pr).
  • Store prototypes and related constants in /COPY members.
  • Use IMPORT and EXPORT only for truly global items that are set once and never changed.
  • Build service programs. Keep related procedures together.

Character String Manipulation

RPG IV has excellent string handling. Use it.

  • Declare string constants as named constants instead of arrays.
  • Use built-in functions (%SCAN, %SUBST, %TRIM, %REPLACE, %CONCAT, etc.) instead of old tricks with arrays or data structures.
  • Prefer free-form EVAL for assignments involving strings.

Avoid Obsolescence

RPG is over 30 years old! 

Many original features are still there but should not be used.

  • Do not sequence line numbers in columns 1-5.
  • Use externally described files (EXTFILE, EXTDESC) instead of program-described files.
  • If a free-format version of an opcode exists, use it (IF instead of IFxx, CALLP instead of CALL, etc.).
  • Prefer built-in functions over opcodes when both do the same job.
  • Avoid CALL, CALLB, PARM, PLIST, DEBUG, FREE, and other obsolete opcodes.

Final Advice

When good style and raw performance conflict, choose good style.

Always:

  • Make it right before you make it faster.
  • Keep it right when you make it faster.
  • Make it clear before you make it faster.
  • Never sacrifice clarity for tiny gains in efficiency.
  • Put only one keyword per line in all specification types that support keywords.
  • If you cannot make a piece of code clear without heavy comments, move it into a well-named, well-documented subprocedure.

Hard-to-read programs are hard to debug, hard to maintain, and hard to get right.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>