21
Sat, Dec
3 New Articles

The API Corner: Still Using Compile-Time Arrays?

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

There are better ways for storing textual information.

 

As a contract programmer, I have the opportunity to review quite a bit of i-based code that is to be rewritten as part of various modernization efforts. One programming style that I encounter fairly often is the use of compile-time arrays to store textual information for use on displays and reports. These companies' databases may have, for instance, an order-status field (OrdSts) with values such as P, O, C, H, I, R, and S to represent order pending, order, order canceled, order held by accounting, order held due to inventory, order released for processing, and order shipped, respectively. When returning order status information to a user, the application programs may then utilize a compile-time array, as shown below, to provide a textual description of the order status through a display or printer file character variable (Status).

 

     dTxt              s             30    dim(8) ctdata 

                                                         

     dOrdSts           s              1                  

     dStatus           s             25                  

                                                         

      /free                                              

                                                         

       // Read a record containing order status (OrdSts) 

       select;                                            

          // Provide text description of order status

          when OrdSts = 'P';                             

               Status = Txt(1);                          

          when OrdSts = 'O';                              

               Status = Txt(2);                          

          when OrdSts = 'C';                             

               Status = Txt(3);                          

          when OrdSts = 'H';                             

               Status = Txt(4);                          

          when OrdSts = 'I';        

               Status = Txt(8);     

          when OrdSts = 'R';        

               Status = Txt(5);     

          when OrdSts = 'S';        

               Status = Txt(6);     

          other;                    

               Status = Txt(7);     

       endsl;                       

 

       // Do processing, including output of 

       // order status in textual form       

                                              

       *inlr = *on;                 

       return;                      

 

      /end-free                                           

**CTDATA TXT                        

Order pending              

Order scheduled            

Order canceled             

Order held - Accounting    

Order being processed      

Order shipped              

Order status is unknown    

Order held - Inventory     

 

While this approach to providing human-readable text descriptions of the order status is certainly time-proven (I've seen it in various forms of RPG for well over 30 years), it also irritates me (admittedly to a degree perhaps out of proportion, but an irritation all the same).

 

The major concern I have with this approach is that when a change is needed to the OrdSts textual description, then development must…

 

  • Locate each program mapping OrdSts to a textual description.
  • Edit each program and modify the compile-time array source.
  • Recompile each changed program.
  • For many companies, then run a regression test bucket to ensure no bug was introduced (missing override during compile, incorrect /copy included, inadvertent deletion of a source line, etc.).

 

There are many ways to minimize this development effort, including approaches such as these:

 

  1. Define the textual descriptions in a separate source member and use /copy to include this member into the application program. This does eliminate the need to go into each program; it still leaves us with the steps of locating the impacted programs, recompiling the programs (to include the modified source of the Txt array), and retesting.
  2. Remove the Txt array from the application program source and add the textual descriptions as conditioned character constants to the display and printer file. This does eliminate the need to edit and recompile each program, but it moves the source maintenance to the display and/or printer file, which could easily make the situation worse as we've now added indicators to condition the character constants (which, as an aside, can eventually lead you to the conclusion that 99 indicators is insufficient for many applications). This method also still requires you to locate, modify, recompile, and retest the display and printer files.
  3. Remove the Txt array from the application program source and store the Status descriptive text as separate records/rows in a keyed database file. The application program can then access the text using the appropriate key and move the descriptive text to the Status variable.
  4. Remove the Txt array from the application program source and store the Status descriptive text as separate message descriptions in a message file. The application program can then access the text using the appropriate message ID and move the descriptive text to the Status variable.

 

Approaches 3 and 4 succeed in externalizing the descriptive text from the application program and eliminate the need to locate application source (whether it be an RPG application program or a DDS display/printer file), edit the source, and recompile the source—which in many cases also results in less need for a full regression test in order to change the text associated with OrdSts.

 

My preference is to use the fourth approach—message descriptions and message files. This article won't go into the implementation details behind this preference (though future articles will), but one example of why I prefer message descriptions over database fields is due to the ability for the i message-handler support to imbed replacement data within the returned text—without the application program having to explicitly control the concatenation of data and text, which would be more the case using database support.

 

To move the descriptive text to message descriptions, we can create a message file, named TextMsgs, and add the appropriate message descriptions as shown below.

 

CRTMSGF MSGF(TEXTMSGS)

ADDMSGD MSGID(DSP0100) MSGF(TEXTMSGS) MSG('Order pending')

ADDMSGD MSGID(DSP0101) MSGF(TEXTMSGS) MSG('Order scheduled')       

ADDMSGD MSGID(DSP0102) MSGF(TEXTMSGS) MSG('Order canceled')        

ADDMSGD MSGID(DSP0103) MSGF(TEXTMSGS) MSG('Order held - Accounting')

ADDMSGD MSGID(DSP0104) MSGF(TEXTMSGS) MSG('Order held - Inventory')

ADDMSGD MSGID(DSP0105) MSGF(TEXTMSGS) MSG('Order being processed') 

ADDMSGD MSGID(DSP0106) MSGF(TEXTMSGS) MSG('Order shipped')         

ADDMSGD MSGID(DSP0107) MSGF(TEXTMSGS) MSG('Order status is unknown')

 

Having added the message description to TEXTMSGS, we now need to access these descriptions from the application program. As you might expect, there's an API for that. The API is Retrieve Message (QMHRTVM) and is documented here. The QMHRTVM API has many capabilities we will not be taking advantage of today. The essential part that we will be using initially is that, given a message ID (and message file), the API can return the first-level text of the message description. In the next article, we'll look at one possible implementation of a *SRVPGM export RtvMsgTxt (Retrieve Message Text) which utilizes this API. In the meantime, feel free to review the API documentation and see if you can write your own implementation of RtvMsgTxt.

 

The RtvMsgTxt procedure we'll be developing returns first-level message text and will be utilized as shown in the following program.

 

h bnddir('MSGSPTBD')                                       

                                                            

dRtvMsgTxt        pr                                       

dMsgRcv                      65535a   options(*varsize)    

dLenMsgRcv                      10i 0 const                

dMsgID                           7a   const                

                                                           

dOrdSts           s              1                         

dStatus           s             25                         

                                                            

 /free                                                     

                                                           

  // Read a record containing order status (OrdSts)        

  select;                                                   

     // Provide text description of order status           

     when OrdSts = 'P';                                    

          RtvMsgTxt(Status :%size(Status) :'DSP0100'); 

     when OrdSts = 'O';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0101'); 

     when OrdSts = 'C';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0102'); 

     when OrdSts = 'H';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0103'); 

     when OrdSts = 'I';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0104'); 

     when OrdSts = 'R';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0105'); 

     when OrdSts = 'S';                                

          RtvMsgTxt(Status :%size(Status) :'DSP0106'); 

     other;                                            

          RtvMsgTxt(Status :%size(Status) :'DSP0107'); 

  endsl;                                                

                                                       

  // Do processing, including output of   

  // order status in textual form         

                                          

  *inlr = *on;                             

  return;                                 

                                          

 /end-free                                

 

These are the changes made to the original sample program:

 

  • Specify the binding directory MSGSPTBD on the H-spec. In the next article, we'll create this binding directory and add the *SRVPGM MSGSPT to it.
  • Prototype the exported RtvMsgTxt procedure with three parameters. The parameters respectively correspond to the variable where the message text will be returned, the size of the variable where the message text is returned (the size of the first parameter), and the seven-character message ID identifying the message to be returned. In my implementation of RtvMsgTxt, the procedure will determine the appropriate message file based on the three-character prefix (DSP in the sample scenario) of the message ID. Having RtvMsgTxt determine the message file removes the need for the developer to specify the message file (most likely the same) with every call of the RtvMsgTxt procedure.
  • Replace all references to the Txt compile-time array entries with calls to the RtvMsgTxt procedure. When calling the procedure, the three parameters passed are Status, %size(Status), and the appropriate message ID. This can be accomplished with minimal effort by simply scanning for the string 'Txt(' and specifying the correct message ID for the third parameter passed to RtvMsgTxt.
  • Remove the definition of the Txt array along with the source records associated with the array.

 

With these changes to how the order status descriptive text is retrieved, we can now change the text with the Change Message Description (CHGMSGD) command and not have to locate, change, and recompile the source of any application program, display file, or printer file that is utilizing the text. We could, going admittedly to an extreme for some companies, even change the English description to Spanish and not have to recompile the application program (though in the case of a language change such as English to Spanish we would most likely want to also translate any *DSPF and *PRTF column headings, prompts, etc.—not related to Order Status though—to also be in Spanish).

 

Those of you familiar with the DDS keyword MSGID might be wondering why I'm using a RtvMsgTxt approach rather than simply using the variable support of the MSGID keyword to provide the message text. If I knew with certainty that the textual form of OrdSts would be needed only for display files, I might very well take that approach. I don't know with certainty though what the future might hold—and if that future includes printer files, I would then run into the problem that printer files do not support the MSGID DDS function, leaving me still with the need to provide order status descriptive text under application program control. Because I prefer one solution that can be applied across all scenarios, I would go with a RtvMsgTxt-based solution.

 

The benefit of storing the descriptive text external to the application program is not one that, in my opinion, warrants going out and changing existing applications solely for the purpose of eliminating compile-time arrays (or conditioned text in *DSPFs and *PRTFs). It is, however, a solution that can be easily implemented as you are updating existing applications and/or writing new application programs. And the ease of implementation is one where the additional cost of making such an enhancement is minimal.

 

Next month, we'll look at some of the specifics in using the QMHRTVM API. In the meantime, if you have any API questions send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.   

 

as/400, os/400, iseries, system i, i5/os, ibm i, power systems, 6.1, 7.1, V7,

 

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: