21
Sat, Dec
3 New Articles

Ten Simple Rules for Using Subprocedures

RPG
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

When it comes to building programs with RPG IV, storing the source in a single, large source member is no longer a viable programming practice. The use of subprocedures, modules, and service programs can cause some confusion, but by organizing your source code in a sensible way, you can make using these cool new tools much easier.

Below, I've listed the 10 guidelines that I've found to be most helpful when creating new applications with RPG IV. While I've labeled them "rules," they are merely guidelines that you might consider for implementation. Feel free to alter them, avoid them, or add your own.

Rule #1: Do not keep all of your source code in one source file.

This is perhaps the most perplexing practice I have seen. People create a source file named QSOURCE or something similar, and they store all the RPG, DDS, and CL source in that one source member.

This is not a safe thing to do. If you lose the file, you lose everything you have on your system. Thank goodness, the OS/400 operating system is the most reliable on the market. If this were Linux, Windows, or anything else, odds are good that you would have lost your source by now.

Keeping source in the standard QRPGLESRC, QDDSSRC, and QCLSRC source files is a good practice. At minimum, my recommendation is that you keep source in the standard source file names. Then, if you want more flexibility, break them out into libraries for each application category. For example, create an A/R source library and an Order Entry source library, each with its own QRPGLESRC, QDDSSRC, and QCLSRC source files. That way, backups will be faster, only changed source needs to be backed up, finding source will be easier (because you know that the invoicing program's source is in the A/R library's source member), and you have easier integration with current PC-based development tools such as CODE/400 or WDSc.

Rule #2: Do not put all of your subprocedures into a single source member.

With subprocedures, I see a lot of an "all or nothing" technique being practiced. Placing all your subprocedures into one source member is counterproductive. The purpose of subprocedures and modules is to allow you to break up your source into related components. Practice the art of placing related procedures into a source member. This yields multiple source members based on category or purpose. For example, all the pricing subprocedures might go into one source member, and all the subprocedures that calculate the weight of an order might go into another.

If the source member gets too big, start a new one with a similar name and place new procedures in it. A good rule of thumb is that if the source member gets too lengthy--more than about 2,000 lines of code--consider breaking it up or starting a second source member.

Rule #3: Do not limit source members to one subprocedure each.

Going the opposite direction of Rule #2, don't get too caught up in breaking apart your source code. Creating a source member with one or two subprocedures isn't wrong, but it should be done only on an exception basis. For example, when the subprocedures are not related to anything else in the application you are building, then stick them in their own source member. But don't create a one-to-one correspondence between source members and subprocedures. That will just create too much source to manage and actually cause the poor RPG programmer who is still stuck using SEU to have nightmares.

Rule #4: Group related subprocedures together in a single source member.

This is probably the most practical guideline; group related subprocedures in the same source member. If the source member gets too big, then follow the guidelines from rule #2 and break it up. The point of this guideline is really the opposite of what it says; you should avoid placing unrelated subprocedures into the same source member.

Create source members and, in them, store subprocedures that are related or support one another. Avoid placing all the subprocedures for a particular application or service program into the same source member just because there are only a few of them. Down the road, as the application grows, you'll appreciate the ability to maintain it more easily by editing the individual source member.

Rule #5: Put prototypes in a separate source member.

Repeat after me: "I will not hard-code prototypes in my source; I will not hard-code prototypes in my source." When you create a new subprocedure, move the prototype outside of that source member and into a source member that contains only prototypes, no executable code. Then, using /COPY or the new /INCLUDE, import the prototypes into each source member that will be calling your subprocedures.

This technique is key to using subprocedures. I know that many (most?) RPG programmers have never used /COPY--which is disappointing--but /COPY or /INCLUDE is critical to using subprocedures and, consequently, modules in your application development.

Place all prototypes into source members that contain nothing but prototypes. They can also contain declarative statements, if necessary, and while there are tricks available to allow executable code to be specified as well, source members that contain prototypes should not contain any executable code.

Rule #6: Create service programs using multiple modules with related function.

Creating your first service program is a big event, sort of like it was for most of us when we first used a fax machine. After awhile, the newness of the technology will wear off, and you'll get used to using them, without the mystique originally felt.

When creating service programs, you should design them so that they contain related routines or libraries of functions. You have more flexibility with service programs than you do with source members, because you can store multiple modules in the service programs. You should consider creating a service program for your A/R subprocedures. Your A/R subprocedures may be scattered across multiple source members and, hence, multiple module objects. All these modules may be combined into a single-service program.

If you want to provide even more flexibility, you might consider multiple-service programs per category. Just like source members, if a service program contains too much stuff, it can become unmanageable. Creating additional service programs that are related--with fewer modules and hence fewer subprocedures--can solve this manageability issue.

An example of this is the RPG ToolKit. It is currently composed of approximately a dozen modules and dozens of subprocedures. At some point in the future, as the CGI functionality of the ToolKit grows, we plan to break out the CGI functions into their own service programs. We also plan to do that with the IFS functions and the base functions, so you may end up with three or four service programs.

Rule #7: Never use CALLP to call a secondary module in a program.

In the original version of RPG IV on OS/400 V3R1, IBM did not provide the ability to write subprocedures using RPG IV. However, IBM did provide the CALLB operation code in V3R1.

In order to illustrate how the CALLB operation code works, IBM used a program that consisted of two *MODULE objects; both were RPG IV source members with mainline calcs (i.e., the RPG cycle).

The CALLB called the second module by name, taking advantage of a feature in the RPG IV compiler that automatically generates a subprocedure with the same name as the module when a source member is compiled that contains mainline calculations. That is, the compiler wraps the mainline calcs in a subprocedure whose name is the same as the module (which is usually the same name as the source member).

So "calling a module" became a technique that people began believing was a viable design decision. When I see developers implementing this technique, I realize that they don't have a clue about how to use subprocedures. They think they're using "ILE" because they included a CALLB (or CALLP) in their code. This technique reminds me of a person who paints a garage door with a can of latex paint and thinks he has just painted the Mona Lisa.

Bottom line: Don't call a module.

Rule #8: Always use NOMAIN in secondary source members.

To help with Rule #7, this guideline recommends that when you're creating a secondary source member (that is, a source member that will be a part of an application but not the entry point for the application), always, always, always use the NOMAIN keyword on the Header specification.

The NOMAIN keyword will cause a compiler error to be generated if the source member containing it is compiled with any mainline calculations present. This will certainly help maintain a good application design and weed out any of those crazy "calling a module" techniques.

NOMAIN also instructs the compiler to avoid inserting the nearly 12,000 lines of code that are used by the RPG cycle. Without the overhead of the RPG cycle start-up routine, calling procedures is a whole lot faster. In fact, calling a module requires the RPG cycle to be present; hence, anything you save by doing a CALLB to the module is lost when the RPG cycle is run.

Rule #9: Subprocedures should do one task and return.

When creating a subprocedure, try to limit the subprocedure to achieving one task and then returning to the caller. Never create a subprocedure that does everything. It is counterproductive because it makes the code unreadable.

One of the side effects of making your subprocedures do one task and then return is that they are readable by maintenance programmers. If you limit a procedure to one task and that task is only 50 lines of code, the maintenance programmer can quickly comprehend the logic and flow of the subprocedure and more easily do what needs to be done to modify it or enhance it.

A good rule of thumb is if a procedure is more than one page long, it's probably getting too complicated. But what is "one page" today? With comments and declaration statements, a subprocedure should be only a few dozen lines long. If you need a hard number as a guideline, then consider this; if a subprocedure is more than 250 lines of code (and that's a big number), it is too big for a maintenance programmer--and often the original programmer--to easily comprehend. So keep them small and on task.

Rule #10: Habitually export all subprocedures.

When you create a new subprocedure, it is not available to the outside world unless it is exported. Often, programmers will build a standalone application with embedded subprocedures (i.e., subprocedures coded in the same source member as the mainline calcs). Then later, as the application development evolves, they will move those subprocedures into a secondary source member. Often this leads to a "compilation failed during bind phase" error when you compile.

This type of error is usually caused because you did not specify the EXPORT keyword on the Subprocedure specification ("P spec"). You can avoid this type of error by always and automatically entering the EXPORT keyword on the P spec whenever you create a new subprocedure. The only time you want to avoid the EXPORT keyword is when you do not want it to be called from outside of the source member in which is specified. In this case, it is always easier to go back and remove an EXPORT keyword than it is to remember why you're getting that "binder phase" error.

So there you have it, 10 simply rules for using subprocedures. Make them part of your shop's standards.

Bob Cozzi has been programming in RPG since 1978. Since then, he has written many articles and several books, including The Modern RPG Language --the most widely used RPG reference manual in the world. Bob is also a very popular speaker at industry events such as RPG World and is the author of his own Web site and of the RPG ToolKit, an add-on library for RPG IV programmers.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: