Training BOB to be an RPG EXPERT and use Coding Standards

This is my (evolving) source code update request:

I want IBM BOB to work as efficiently as possible for our team of IBM-i programmers. Create coding standards templates for all IBM-i languages, based on best practices for modern RPG application development. All standards will be using CODE FOR IBM-i extension. Rules.mk will follow CODE FOR IBM-i and MAKEI standards. Create all necessary helper files and templates for this NICKLITTEN project. Specify rules for code scanning, template application, comment handling, and auto-insertion/correction of comment blocks. Create any profile files that are needed for BOB to repeat this for all future requests.

## Key Documentation Principles
- For all source types, ALWAYS use '-' as comment line seperator character. Never use '='.
- For RPGLE and SQLRPGLE add 'ctl-opt copyright(version - description)' using the program description and version number calculated from number of modifications in the history
- For CLLE add 'COPYRIGHT TEXT('version - description') using the program description and version number calculated from number of modifications in the history
- for Author use 'Nick Litten'

### 1. Triple-Slash Format (///)
- Use triple slashes for all program-level documentation for RPGLE and SQLRPGLE
- Use /* (comments) */ for all program-level documentation for CLLE and CMD
- ' *' for all DDS comments
- '--' for all SQL comments
- Provides better IDE integration and parsing
- Distinguishes documentation from regular comments

### 2. Clear Structure
- **Program/Service Name**: Always include at the top
- **Description**: Comprehensive explanation of purpose
- **Purpose**: Bullet list of key concepts demonstrated
- **Features**: Specific capabilities and highlights
- **Usage**: Clear examples of how to use the program
- **Modification History**: Track all changes with dates

### 3. Feature Lists
Use bullet points to highlight:
- Technical capabilities
- Design patterns demonstrated
- Best practices implemented
- Integration points
- Performance considerations

### 4. Educational Value
For example programs, emphasize:
- What concepts are being taught
- Why certain approaches are used
- How the code demonstrates best practices
- Links to related examples or documentation

### 5. Practical Information
Include:
- How to compile the program
- Required dependencies
- Parameter descriptions
- Expected input/output
- Error handling approach

IBM BOB - in progress

Training BOB to be an RPG EXPERT and use Coding Standards - Completed (1)
Training BOB to be an RPG EXPERT and use Coding Standards - Completed (2)
Training BOB to be an RPG EXPERT and use Coding Standards - Completed (3)
Training BOB to be an RPG EXPERT and use Coding Standards - Completed (4)
Training BOB to be an RPG EXPERT and use Coding Standards - Completed (5)

The template files BOB generates are clean, modern and extremely readable!

Now you just open any source code and tell BOB to "update source comments" and *boom*

Example - BEFORE

**free
// ------------------------------------------------------------------------------
// author: nick litten
// some old sample code written in the 1990s for rpg400 style
// with goto statements and subroutines. this code has been
// converted to free format rpg as part of a video rpg upgrade.
// written : during a 1990's rave
// modification history:
// 2025.10.06 njl played with as part of a video rpg upgrade
// https://www.nicklitten.com/course/old-rpg-with-goto-tag-and-subroutines-to-modern-rpgle-with-sub_procedures
// ------------------------------------------------------------------------------

ctl-opt dftactgrp(*no) actgrp('NICKLITTEN') option(*srcstmt:*nodebugio);

dcl-f qtxtsrc disk usage(*input) rename(qtxtsrc:rectxt);

Dcl-Pi *n;
rtn char(10);
end-pi;

Dcl-Ds srcdta qualified inz;
flag char(8) pos(1);
partnumber char(20) pos(11);
end-ds;

rtn = 'NOT FOUND';

// read every row in QTXTSRC and update 'RTN' if match found
read qtxtsrc;
dow (not %eof(qtxtsrc) and no_match_found(srcdta.flag:srcdta.partnumber));
read qtxtsrc;
enddo;

dsply %char('Rtn=' + rtn);

*inlr = *on;

// this is a subprocedure that replaces a goto tag subroutine
Dcl-Proc no_match_found;
Dcl-Pi *n ind;
myFlag like(srcdta.flag);
myPartnumber like(srcdta.partnumber);
end-pi;
Dcl-S myStatus ind inz(*on);

If myFlag = 'THISONE' and myPartnumber <> *BLANKS;
rtn = 'EXISTS';
myStatus = *off;
EndIf;

Return myStatus;
end-proc;

Example - AFTER

**free
// ------------------------------------------------------------------------------
// Program: OLDTAGRPG3 - Old RPG400 Modernized Example
// Author: Nick Litten
//
// Description:
//   Sample code originally written in the 1990s using RPG400 style with GOTO
//   statements and subroutines. This version has been modernized to free-format
//   RPG with subprocedures, demonstrating the evolution from legacy to modern
//   RPG programming practices.
//
// Written: During a 1990's rave
//
// Modification History:
//   2025.10.06 NJL - Initial modernization as part of video RPG upgrade
//   2026.04.18 NJL - Updated source comments and documentation
//
// Reference:
//   https://www.nicklitten.com/course/old-rpg-with-goto-tag-and-subroutines-to-modern-rpgle-with-sub_procedures
// ------------------------------------------------------------------------------
ctl-opt dftactgrp(*no) actgrp('NICKLITTEN') option(*srcstmt:*nodebugio);
dcl-f qtxtsrc disk usage(*input) rename(qtxtsrc:rectxt);
Dcl-Pi *n;
   rtn char(10);
end-pi;  
Dcl-Ds srcdta qualified inz;
   flag char(8) pos(1);
   partnumber char(20) pos(11);
end-ds;
rtn = 'NOT FOUND';
// read every row in QTXTSRC and update 'RTN' if match found
read qtxtsrc;
dow (not %eof(qtxtsrc) and no_match_found(srcdta.flag:srcdta.partnumber));
   read qtxtsrc;
enddo;
dsply %char('Rtn=' + rtn);
*inlr = *on;
// Subprocedure: no_match_found
// Purpose: Replaces legacy GOTO/TAG subroutine logic with modern subprocedure
// Returns: *ON if no match found, *OFF if match exists
Dcl-Proc no_match_found;
   Dcl-Pi *n ind;
      myFlag like(srcdta.flag);
      myPartnumber like(srcdta.partnumber);
   end-pi;
   Dcl-S myStatus ind inz(*on);
   If (myFlag = 'THISONE' and myPartnumber <> *BLANKS);
      rtn = 'EXISTS';
      myStatus = *off;
   EndIf;
   Return myStatus;
end-proc;
{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>