• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Guru: Growing A More Productive Team With Procedure Driven RPG

    June 24, 2024 Gregory Simmons

    There are many great benefits to procedure driven RPG, and I have covered many of them in my previous articles. In this article, I want to share with you what I believe is the biggest benefit to implementing procedure driven RPG in your shop; procedures, when written and implemented properly, are reusable.

    When you’ve written a new procedure that expertly tackles one task, you should be proud of the accomplishment. But don’t keep that in your program. Export it in a service program for your whole team to use! Now, undoubtedly, you will find yourself at one point thinking: “Yeah, but I can’t see anyone else in our shop needing this procedure.” And you may be right. But the key to cashing in on this benefit is to start writing procedures that are focused on one task and export them all from service programs. ALL of them.

    Let’s walk through how to take a procedure in a program and export it in a service program. Here I’ve written a sample program that will retrieve the day of the week (1, 2, 3, etc.).

    **Free
    Ctl-Opt Main(Process_Rebate_Checks);
    Ctl-Opt ActGrp(*Caller);
    
    Dcl-Proc Process_Rebate_Checks;
    
    Dcl-s nDayOfWeek Uns(3);
    
    // Processing Rebate Check logic…
    
    nDayOfWeek = get_day_of_week(%Date());
    
    // Remaining Rebate Check Logic…
    
    On-Exit;
    End-Proc Process_Rebate_Checks;
    
    Dcl-Proc get_day_of_week;
    
    Dcl-Pi get_day_of_week Uns(3);
      InputDate Date Const;
    End-Pi;
    
    Dcl-s result Uns(3);
    
    Test(e) InputDate;
    If %Error;
      Return -1;
    Endif;
    
    Exec SQL
      Set :result = DayOfWeek(:InputDate);
    
    If SQLState <> SQL_Success;
      Return -1;
    EndIf;
    
    Return result;
    
    On-Exit;
    End-Proc get_day_of_week;
    

    In the above example, I needed to know what day of the week was, so I am accomplishing that in the procedure get_day_of_week. It’s pretty simple. I check that the date passed in is a valid date, and then use the SQL function DayOfWeek to get the number and return the answer.

    Now, let’s move this procedure to a new service program called dateutils.

    First, we’ll create a new copybook to hold the prototype. This is key, as it lets everyone else who wants to use this procedure use the /copy compiler directive to bring in all of the procedure interfaces into their program. Another benefit of putting procedure types in copy books is that if/when a procedure prototype changes, your program may not need to be recompiled. For example, if someone added a parameter with options(*Nopass), no recompiling would be necessary. So, the copy book, called dateutilsc, looks like this:

    **Free
    Dcl-Pi dateutils_get_day_of_week Uns(3);
      InputDate Date Const;
    End-Pi;
    

    Next, we’ll create a new source member which will later be compiled into a module.

    **Free
    Ctl-Opt NoMain;
    
    /copy dateutilsc
    
    Dcl-Proc dateutils_get_day_of_week;
    
    Dcl-Pi dateutils_get_day_of_week Uns(3);
      InputDate Date Const;
    End-Pi;
    
    Dcl-s result Uns(3);
    
    Test(e) InputDate;
    If %Error;
      Return -1;
    Endif;
    
    Exec SQL
      Set :result = DayOfWeek(:InputDate);
    
    If SQLState <> SQL_Success;
      Return -1;
    EndIf;
    
    Return result;
    
    On-Exit;
    End-Proc dateutils_get_day_of_week;
    

    The /copy of the copybook dateutilsc, again, brings in the prototype of the procedure. By default, the RPG compiler looks for that copybook in QRPGLESRC in your library list. In my previous shop, we kept our copy books in QCPYSRC. Either will work fine, just remember that if you choose to store your copy books in a source physical file other than QRPGLESRC or in a different library, you’ll need to specify the /copy with one of these formats:

    /copy libraryname/filename,membername
    /copy filename,membername
    /copy membername
    

    The only difference for the rest of the procedure, which is totally optional, is that I like naming the procedures in a service program such that they all start with the name of the service program. In that way, when reading code that calls a procedure in a service program, you automatically know in which service program to find that procedure.

    Next, this is not necessary, but I find it nicer to create binder source. This simply tells the compiler which procedures or ‘symbols’ to export. I created a dateutils.bnd source in QBNDSRC:

          STRPGMEXP  PGMLVL(*CURRENT) LVLCHK(*NO)
            EXPORT     SYMBOL(dateutils_get_day_of_week)
          ENDPGMEXP
    

    This is a very brief introduction to binder language. You can read more on binder language here: https://www.ibm.com/docs/en/i/7.4?topic=concepts-binder-language

    Okay, now compile the module. Then create the service program.

    Now, the program I pulled this procedure out of looks like this:

    **Free
    Ctl-Opt Main(Process_Rebate_Checks);
    Ctl-Opt ActGrp(*Caller);
    Ctl-Opt Bnddir(Utils);
    
    /copy dateutilsc
    
    Dcl-Proc Process_Rebate_Checks;
    
    Dcl-s nDayOfWeek Uns(3);
    
    // Processing Rebate Check logic…
    
    nDayOfWeek = dateutils_get_day_of_week(%Date());
    
    // Remaining Rebate Check Logic…
    
    On-Exit;
    End-Proc Process_Rebate_Checks;
    

    Note that the only changes are that I added the Ctl-Opt at the top to tell the compiler that it can check the Utils binding directory for the procedures I’m calling. I then added the compiler directive /copy of dateutilsc, changed the name of the procedure from get_day_of_week to dateutils_get_day_of_week and deleted the procedure as it now lives in the service program for all to utilize.

    This next step, while not necessary, is a good practice, especially when your programs start needing to call procedures in multiple service programs. In a nutshell, this is just providing a list of service programs and/or modules where the compiler can go find the procedures your program is referencing. If you don’t want to use binding directories, you just need to specify which service programs to reference on the compile command. If you do this, I think you will pretty quickly find that binding directories are the way to go. Creating the binding directory is pretty simple to set up in just two steps:

    Create the binding directory: CRTBNDDIR BNDDIR(MYLIB/UTILS) TEXT(‘Binding directory for Utility Service Programs’)

    Add the service program to the newly created binding directory: ADDBNDDIRE BNDDIR(MYLIB/UTILS) OBJ((MYLIB/DATEUTILS *SRVPGM *DEFER))

    Again, this is a very quick introduction to binding directories. If this is your first exposure to them, I highly recommending doing some further research.

    Now, I’m ready to compile my new slimmed down program. Well, to be accurate, the compiled object itself has not shrunk, but the source member has.

    Until next time, happy coding.

    Gregory Simmons is a software engineer with PC Richard & Son. He started on the IBM i platform in 1994, graduated with a degree in Computer Information Systems in 1997 and has been working on the OS/400 and IBM i platform ever since. He has been a registered instructor with the IBM Academic Initiative since 2007, and holds a COMMON Application Developer certification. When he’s not trying to figure out how to speed up legacy programs, he enjoys speaking at technical conferences, running, backpacking, hunting, and fishing.

    RELATED STORIES

    Guru: With Procedure Driven RPG, Be Precise With Options(*Exact)

    Testing URLs With HTTP_GET_VERBOSE

    Guru: Fooling Around With SQL And RPG

    Guru: Procedure Driven RPG And Adopting The Pillars Of Object-Oriented Programming

    Guru: Getting Started With The Code 4 i Extension Within VS Code

    Guru: Procedure Driven RPG Means Keeping Your Variables Local

    Guru: Procedure Driven RPG With Linear-Main Programs

    Guru: Speeding Up RPG By Reducing I/O Operations, Part 2

    Guru: Speeding Up RPG By Reducing I/O Operations, Part 1

    Guru: Watch Out For This Pitfall When Working With Integer Columns

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags: Tags: 400guru, FHG, Four Hundred Guru, IBM i, RPG

    Sponsored by
    ARCAD Software

    Demystifying GitFlow and Branching for the IBM i

    There are a variety of branching strategies for Git, all with their benefits and challenges. In this webinar, we will feature Gitflow which utilizes the core feature of Git and the power of branches. Join Jeff Tickner, CTO NA, and Sr. Solution Architects, Ray Bernardi and Alan Ashley on this important topic as they explain and demonstrate:

    • What is Gitflow and the benefits?
    • Bi-directional development with push/pulls and merging conflicts. Why you need this 2-way integration?
    • Flexible Gitflow options.
    • How this applies to the IBM i with features, releases and hotfixes.
    • How ARCAD’s tooling elegantly supports Gitflow for the IBM i Developer.

    Join our webinar to discover the benefits of Gitflow and how it enhances development processes with flexible options and seamless integration on IBM i.

    REGISTER NOW

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    The 13,152 Days Of The AS/400 Platform, And Counting Profound Brings GenAI Tech To IBM i Apps with Profound AI

    One thought on “Guru: Growing A More Productive Team With Procedure Driven RPG”

    • Dan says:
      June 25, 2024 at 1:41 pm

      While there is a lot of benefit to standardizing “utility” functions like this into a service program, I believe the greatest benefit is to get core business logic functions in a service program so that there is exactly one place where this logic exists and you don’t have 100 programs that use said logic coded in each program. You need to change that core business logic? Would you rather make the change in one place or 100? If the latter, are you sure you got all 100 correctly updated? Oh wait, the logic in some programs use different variable names? I inherited this exact nightmare in a previous job.

      Reply

    Leave a Reply Cancel reply

TFH Volume: 34 Issue: 31

This Issue Sponsored By

  • Fresche Solutions
  • WorksRight Software
  • ARCAD Software
  • OCEAN User Group
  • Raz-Lee Security

Table of Contents

  • Celerity Buys Chilli IT To Expand Its Power Systems Business
  • Profound Brings GenAI Tech To IBM i Apps with Profound AI
  • Guru: Growing A More Productive Team With Procedure Driven RPG
  • The 13,152 Days Of The AS/400 Platform, And Counting
  • IBM i PTF Guide, Volume 26, Number 23

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • POWERUp 2025 –Your Source For IBM i 7.6 Information
  • Maxava Consulting Services Does More Than HA/DR Project Management – A Lot More
  • Guru: Creating An SQL Stored Procedure That Returns A Result Set
  • As I See It: At Any Cost
  • IBM i PTF Guide, Volume 27, Number 19
  • IBM Unveils Manzan, A New Open Source Event Monitor For IBM i
  • Say Goodbye To Downtime: Update Your Database Without Taking Your Business Offline
  • i-Rays Brings Observability To IBM i Performance Problems
  • Another Non-TR “Technology Refresh” Happens With IBM i TR6
  • IBM i PTF Guide, Volume 27, Number 18

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle