22
Sun, Dec
3 New Articles

Practical RPG: Converting to Free-Form RPG, Part 2

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

I'm not one to get rid of something that isn't broken, but I'm not sorry to see KLISTs go away.

Given the limitations of columnar RPG, the KLIST was a clever way to allow a programmer to specify a variable number of fields to access a keyed file, but at a price of a lot of lines of code for even simple jobs. Thankfully, free-format RPG has given us a way to do away with those many lines of code.

PLIST and KLIST: Alike but Not Identical

Like PLIST/PARM, the KLIST/KFLD keyword combination effectively creates a multiple-line statement allowing us to specify multiple arguments to the I/O opcodes, such as CHAIN and READE. However, something as simple as a loop with a partial key and a starting position requires multiple KLIST definitions, and as your access to the database becomes more complex and varied, so too do your KLISTs.

As I showed in my previous article, PLISTs have given way to the prototype. The prototype is far more than a simple replacement for the PARM/PLIST construct. Because it deals with so many different variations—as just one example, the same basic construct has to support calls to COBOL, CL, RPG, and Java—the prototype concept is syntactically complex.

The KLIST has a more-specific function: simply to provide access to a keyed file. It's no less important, but because the focus is on only that one thing—providing data to the underlying database support—it can take a more streamlined approach, as we'll see.

Simple KLIST Processing

Let's start with the simplest case. In this situation, we want to get all PO receipts for a specific item from a vendor. We assume a logical file, let's say PURRCTL1, by vendor and item. The KLIST definition shouldn't be too surprising:

     C    PURRCTK1      KLIST

     C                  KFLD                    PRVEND

     C                  KFLD                    PRITEM

Nothing out of the ordinary here. The only question is where the variables PRVEND and PRITEM are defined. In this case, we're going to take a page out of a software vendor's approach and use the actual database fields from the PURRCTL1 file to define the KLIST. Thanks to some reasonable naming conventions (I'm all about naming!), we can create a KLIST with a name that matches the logical file and we're in pretty good shape. The only trick now is to use that value.

I'm going to do a little programming gymnastics here and switch to free-format. You probably know that you can freely intersperse the two syntaxes, so it's not impossible to have free-format calculation specs that use a KLIST. Using a KLIST is pretty simple:

       PRVEND = S1VEND;

       PRITEM = S1ITEM;

       setll PURRCTK1 PURRCTL1;

       reade PURRCTK1 PURRCTL1;

       dow not %eof(PURRCTL1);

         addSubfile1();

         reade PURRCTK1 PURRCTL1;

       enddo;

It's not immediately obvious, but the fields S1VEND and S1ITNO are fields from a screen. Think of this as a subfile in which we want to show all the receipts for the vendor and item specified on the screen. The routine addSubfile1 formats the appropriate data and adds a line to the subfile. This is all quite simple and shows the strengths of the KLIST syntax.

When KLISTs Go Wrong

It's not really wrong, just a bit cumbersome. As well-meaning as the KLIST/KFLD concept may be, it can quickly go off the rails for any sort of complex scenarios. Let's watch how that happens by adding just a tiny complication. In this new case, we want to be able to set our position within the list of receipts using a starting date. To do that, we need a new KLIST.

     C    PURRCTK1S     KLIST

     C                  KFLD                    PRVEND

     C                  KFLD                    PRITEM

     C                  KFLD                    PRDATE

Why the second KLIST? Well, because we need to position within the vendor and item. You've probably done this many times, but let's take a look at the code:

       PRVEND = S1VEND;

       PRITEM = S1ITEM;

       PRDATE = S1DATE;

       setll PURRCTK1S PURRCTL1;

       reade PURRCTK1 PURRCTL1;

       dow not %eof(PURRCTL1);

         addSubfile1();

         reade PURRCTK1 PURRCTL1;

       enddo;

You'll notice one new line of code and one change. First, the new line initializes the date field. Second, we use the second KLIST for the SETLL opcode. This means we don't position to the first record for that vendor and item, but to the first one for that date or later. However, the READE opcode remains the same because we still want to include only the records for that vendor and item.

So now we have two KLISTs, and a lot of lines of code to set the key values. What if we added a second complication?  Let's say we want to do something similar but from a second panel. The code looks like this:

       PRVEND = S2VEND;

       PRITEM = S2ITEM;

       PRDATE = S2DATE;

       setll PURRCTK1S PURRCTL1;

       reade PURRCTK1 PURRCTL1;

       dow not %eof(PURRCTL1);

         addSubfile2();

         reade PURRCTK1 PURRCTL1;

       enddo;

You can see how the code begins to accumulate. Add code for different views and it really begins to multiply quickly, and you end up with a non-executable part of your program that may contain hundreds of lines of code just defining your KLISTs. Worse yet, you need lots of lines of code to initialize your variables, and those lines of code can be far away from the actual I/O opcodes. This leads to bugs when someone adds code that has a side effect of changing the variables in the KLIST.

Free Yourself from KLISTs!

The free-format version of file I/O lets you do away with KLISTs completely. There are actually two different syntactical approaches. One technique uses something called a key data structure and the %KDS built-in function, but I don't use it. I built a small application using just %KDS one time to see how it works. This approach can provide some advantages, especially in environments with very strict naming conventions (and you know how much I love naming conventions!). But in the end, %KDS simply replaces the KLIST with a data structure. And while the data structure is based on the file itself and so tends to be more future-proof than just using work variables in a KLIST, I don't think the advantages are sufficient to justify the approach.

Instead, I prefer a much more localized technique. Specifically, I like to use a key expression right on my opcodes. Here's the code for both loops using the inline approach:

       setll ( S1VEND: S1ITEM: S1DATE) PURRCTL1;

       reade ( S1VEND: S1ITEM) PURRCTL1;

       dow not %eof(PURRCTL1);

         addSubfile1();

         reade ( S1VEND: S1ITEM) PURRCTL1;

       enddo;

    

       setll ( S2VEND: S2ITEM: S1DATE) PURRCTL1;

       reade ( S2VEND: S2ITEM) PURRCTL1;

       dow not %eof(PURRCTL1);

         addSubfile2();

         reade ( S2VEND: S2ITEM) PURRCTL1;

       enddo;

That's all the code. There is no need for additional non-executable code, nor do you need any work variables. I particularly like the fact that you can see exactly which fields you are using for the operation; there's no worry about using variables that might have been changed at some point.

The inline approach has other benefits, which we'll touch upon in later articles. One of my favorite advantages is that you can use expressions right in the code. Let's assume for a moment that the third field in the logical file is a CCYYMMDD date field (yes, I know we prefer dates, but I'll bet you have one or two numeric date fields in your legacy database!). You could easily do something like this:

       setll ( S1VEND: S1ITEM: %dec(%date – 3 %months:*iso)) PURRCTL1;

This syntax will always set the cursor to start three months earlier than today's date. I love it.

So today we learned about the inline key expression in free-format opcodes. You probably also noticed that I used the standard I/O opcode built-in function %eof instead of an indicator. That actually was sort of mandatory, since indicators aren't even supported in the free-format I/O opcodes, but I think they make the code look better, too! But indicators are another area where we can leverage free-format syntax—and more specifically, we can use free-format to get rid of indicators entirely. But that's for another article!

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: