Service Programs are the way to go!
I use them intensively since around 20 years without any problems. Currently I have more than 120 service programs and within these service programs around 8000 exported procedures.
For our service programs we used a few rules:
1. There are almost no internal procedures. Exported procedures must be encapsulated, i.e. parameter in, parameter out and only local variables.
2. One source = one object (program or service program)
3. New procedures must be added at the end of the source
Based on these rules I wrote a small compile command which will automatically generate the binder language, the module, bind the module in the service program, add the service program to the binding directory, delete the module. In this way generating a service program is as simple as compiling a program.
Due to this compile command everybody in my team could add new procedures to service programs and compile them without any problems.
The first version of this compile command was generated in the early 2000s. Until now I have rewritten at least 4 different versions of these commands running on multiple customer machines.
... and we have almost no problems with generating and compiling.
Just in case a service program cannot be bound because a function in another service program is not available (and vice versa). We generate the service programs twice, first time with OPTION(*UNRSLVREF) so the procedures are not resolved. And the second time with OPTION(*RSLVREF) = Default, so the procedures are resolved.
... and I worked with both, i.e. Generated signatures and fixed signatures (and had no problems with none of them).
... and embedded SQL never caused any problems (and I use it intensively)
Mit freundlichen Grüßen / Best regards
Birgitta Hauser
Modernization – Education – Consulting on IBM i
Database and Software Architect
IBM Champion since 2020
"Shoot for the moon, even if you miss, you'll land among the stars." (Les Brown)
"If you think education is expensive, try ignorance." (Derek Bok)
"What is worse than training your staff and losing them? Not training them and keeping them!"
"Train people well enough so they can leave, treat them well enough so they don't want to. " (Richard Branson)
"Learning is experience … everything else is only information!" (Albert Einstein)
-----Original Message-----
From: RPG400-L <rpg400-l-bounces@xxxxxxxxxxxxxxxxxx> On Behalf Of Richard Schoen
Sent: Saturday, 21 March 2026 15:40
To: rpg400-l@xxxxxxxxxxxxxxxxxx
Subject: Re: RPG Service Program vs Include Source for Shared Subprocedures and SQL Calls
Thanks for all the input.
Service Programs seem to make sense.
You’ll have to forgive my relative ignorance on this specific topic.
RPG hasn’t been a primary use language for me in several years so I’m trying to use all the modern goodness.
Now the question is what types of things do you put in your sub procedures and service programs ? In other languages I usually create re-usable functions for things such as:
string handling, file handling, inserting, querying recordsets, updating or deleting records and other small units of work. I guess that’s how I’ve used sub procedures in RPG before as well to date but have used includes mainly.
What about core recordset processing ? Should that specialized logic stay in each individual program or in a sub procedure.
Ex: Create cursor and open it in a sub procedure. Then iterate in the mainline. Then call a sub procedure to close the cursor. Seems a bit overkill. But maybe not if you want to encapsulate all your DB access logic into a single service program for Open, Query, Iterate Next Row, Insert, Update, Delete and Close Cursor.
I suppose it really depends on how many places that logic will be re-used.
There are two examples I can thing of where I might not want to encapsulate logic into a service program.
-When I am processing table a record at a time using record level IO it may not seem to make sense because the open file is in the main module. Or do the service program modules see the open file pointers as well ? In other words does the file open file cross program and procedure boundaries and make it accessible on the inner sub procedure calls ? When a subproc is embedded in an RPG program I believe it can still see the record level opens that are program scoped. Is that the same with service programs ? I guess the summary here is would record level access be appropriate in a service program for chain, read, update, delete.
-Recordset processing with SQL. I can definitely see putting INSERT, UPDATE and DELETE logic in a sub procedure and a DB access service program perhaps, but what about queries that select resulting recordsets. Can I run an SQL from a sub procedure and return the resultset or cursor to the main program like I would in other languages ? I’m guessing I can but most of my embedded SQL has been in single mainline programs and not buried in sub procedures thus far. Also does a named cursor open survive across calls ? I’m starting to visualize it does because you have the CLOSQLSR parm on CRTSQLRPGI which can tell you when to close the cursor.
As with all things software development I’m sure you all have your own patterns that you use. I’m just trying to establish my new ILE pattern thought process since some current projects require a bunch of new RPG coding which will include embedded SQL.
Hope this makes sense :-)
Regards,
Richard Schoen
Web:
http://www.richardschoen.net
Email: richard@xxxxxxxxxxxxxxxxx<mailto:richard@xxxxxxxxxxxxxxxxx>
--
This is the RPG programming on IBM i (RPG400-L) mailing list To post a message email: RPG400-L@xxxxxxxxxxxxxxxxxx To subscribe, unsubscribe, or change list options,
visit:
https://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxxxxxxxx
Before posting, please take a moment to review the archives at
https://archive.midrange.com/rpg400-l.
Please contact support@xxxxxxxxxxxxxxxxxxxx for any subscription related questions.
As an Amazon Associate we earn from qualifying purchases.