fhg
Volume 8, Number 42 -- December 10, 2008

Four Ways to Avoid Problems Caused by Global Data

Published: December 10, 2008

by Ted Holt

Junior J. Programmer modifies an RPG program. His testing works properly. The user's test works properly. The user approves the change, the modified program is installed, and everything is copasetic until a few months later when the program gets stuck in a loop. What happened, and why is Junior not entirely to blame?

Here's the code Junior added to the program:

C     1             DO        5             X                 1 0
C                   EXCEPT    PLINE
C                   ENDDO

What could go wrong with such simple code?

It turns out that the subroutine that contains Junior's code is also conditionally and indirectly executed from another part of the program.

C                   IF        ACCOUNT <> *ZERO
C     1             DO        8             X                 1 0
 ... calcs that indirectly execute Junior's code go here
C                   ENDDO
C                   ENDIF

Since the condition was not directly over the execution of his subroutine (i.e., there were intervening subroutine calls), Junior did not realize that his testing had not covered all conditions. Nor did the user test the conditional logic. The first time ACCOUNT proved not equal to zero, the program went into an infinite loop.

Junior's mistake was in using the X variable to control the loop. His loop messed up the value of X in the outer loop. Since X was already defined as a one-digit packed variable, the compiler did not flag the duplicate declaration.

This example is only one of many ways that a modification to a program can cause an error in another, correctly working section of code. I call these unintended consequences undesirable side effects, and to my way of thinking, the best way to debug undesirable side effects is not to put them into the code in the first place.

In this case, the best way to avoid the infinite-loop problem would be through the use of a local variable, a variable that is known only within a section of code. Global data, on the other hand, is known throughout the entire program. Junior's program went into a loop because X was a global variable.

Ideally, your program should have no global variables, but that is not practical. Here are four ways that you can minimize the use of global variables. You can use these techniques at any current release. (V6R1 presents more opportunities to localize data, but that's a subject for another day.)

1. Use Subprocedures, Not Subroutines

Unlike subroutines, subprocedures can have local data (i.e., variables, constants, and data structures). Local data follows the parameter list. In Junior's case, had the program been written to use subprocedures, he would have added variable X as a local variable to the subprocedure that he modified.

P OneSubProc      b                           
D                 pi                          
D**** parms                                   
 (... parms omitted ...)                      
D*** local                                    
D   X                            1p 0         
 (... code omitted ...)                       
C     1             DO        5             X
C                   EXCEPT    PLINE          
C                   ENDDO                    
 (... code omitted ...)                      
P                 e                          

The subprocedure would have had a variable X, the calling routine would have had its own variable X, and the compiler would have kept them separate.

2. Minimize the Main Declaration and Calculation Specs

Ideally the D specs in the main body of an RPG IV program should be limited to parameter lists, compile-time tables and arrays, and program-wide data structures like the program status data structure. That is not always practical, but the closer you can adhere to this idea, the less chance you have of creating undesirable side effects.

The main calculations should contain a call to one or more subprocedures. Here's an example from a previous article of mine.

H dftactgrp(*no) actgrp(Whatever)
                                           
FXACTS     o    e             disk    usropn
                                            
* ===== *ENTRY PLIST                       
D SomePgm         pr                        
D  inID                          5p 0       
D  inName                       12a         
D SomePgm         pi                        
D  inID                          5p 0       
D  inName                       12a         
                                            
D/copy prototypes,assert                    
D/copy qrpglesrc,psds                       
D SomePgm_Main    pr                        
                                            
 /free                                      
     *inlr = *on;                           
     monitor;                               
        SomePgm_Main();
     on-error;                                        
        assert (*off: 'Unexpected error in program ' +
                      %trim(psdsProcName) +           
                      '. See job log for details.');  
     endmon;                                          
     return;                                          
     // ===========================                   
 /end-free                                            
P SomePgm_Main    b                                   
 /free                                                
     open xacts;                                      
     ID = inID;                                       
     Name = inName;                                   
     write XactRec;                                   
     close xacts;                                     
 /end-free                                            
P                 e

The main program logic is in subprocedure SomePgm_Main, not in the main C specs. The only global data is in the parameter list and the files, but you can address that global data, too.

3. Give Each File a Unique Prefix

In releases before V6R1, all files must be declared globally, which means that all fields defined in files are global. Giving each file a unique prefix, and not using those prefixes on other data, decreases the chances of using a field or variable when it should not be accessed.

I recommend prefixes of one or two letters followed by an underscore.

FCustomer  if   e             disk    usropn prefix(c_)
FMyReport  o    e             printer usropn prefix(p_)

All fields from Customer begin with c_. All fields in the printer file begin with p_. If you don't use these prefixes for anything else, there will be no confusion.

4. Use a Special Prefix for Global Data

I try to prefix global data with a small g. Any other convention is just as good. In the following example, the status parameter, from the program's parameter list, and a tax rate variable are global data.

D QAD2242R        pr                 
D  gStatus                       1a  
D QAD2242R        pr                 
D  gStatus                       1a  
                                     
D gTaxRate        s              9p 6

It goes without saying that this technique is effective only if you do not use a little "g" to begin local data names within subprocedures.

I don't consider Junior completely at fault for introducing a bug into the program. While he should have used a better variable name than X, the original programmer could have written his source code with maintenance in mind.


RELATED STORY

Avoiding the Green Screen of Death in RPG Programs



                     Post this story to del.icio.us
               Post this story to Digg
    Post this story to Slashdot


Sponsored By
PROFOUND LOGIC SOFTWARE

Need Results Fast?
Web-enable with Genie!

                                                          · Easy Installation
                                                          · Codeless Customizations
                                                          · Instant Results

With Genie on your side, you can be
modernized in less than a day. Simply
install, customize, and deploy.

See the magic of Genie today.

Download a FREE 30-day trial at
www.profoundlogic.com


Senior Technical Editor: Ted Holt
Technical Editor: Joe Hertvik
Contributing Technical Editors: Edwin Earley, Brian Kelly, Michael Sansoterra
Publisher and Advertising Director: Jenny Thomas
Advertising Sales Representative: Kim Reed
Contact the Editors: To contact anyone on the IT Jungle Team
Go to our contacts page and send us a message.

Sponsored Links

VAULT400:  Never lose your data with VAULT400's online backup
Computer Keyes:  KeyesOverlay rapidly converts standard *SCS printer files into PDF documents
COMMON:  Join us at the 2009 annual meeting and expo, April 26-30, Reno, Nevada


 

IT Jungle Store Top Book Picks

Easy Steps to Internet Programming for AS/400, iSeries, and System i: List Price, $49.95
Getting Started with PHP for i5/OS: List Price, $59.95
The System i RPG & RPG IV Tutorial and Lab Exercises: List Price, $59.95
The System i Pocket RPG & RPG IV Guide: List Price, $69.95
The iSeries Pocket Database Guide: List Price, $59.00
The iSeries Pocket Developers' Guide: List Price, $59.00
The iSeries Pocket SQL Guide: List Price, $59.00
The iSeries Pocket Query Guide: List Price, $49.00
The iSeries Pocket WebFacing Primer: List Price, $39.00
Migrating to WebSphere Express for iSeries: List Price, $49.00
iSeries Express Web Implementer's Guide: List Price, $59.00
Getting Started with WebSphere Development Studio for iSeries: List Price, $79.95
Getting Started With WebSphere Development Studio Client for iSeries: List Price, $89.00
Getting Started with WebSphere Express for iSeries: List Price, $49.00
WebFacing Application Design and Development Guide: List Price, $55.00
Can the AS/400 Survive IBM?: List Price, $49.00
The All-Everything Machine: List Price, $29.95
Chip Wars: List Price, $29.95


 
The Four Hundred
Soltis Exiting IBM, But He's Not Leaving the '400

A Little More Detail on the Smart Cube and Its Market

IBM's Academic Initiative Partners with DeVry University

Mad Dog 21/21: Potlatch Season

Server Sales Decline in the Third Quarter

The Linux Beacon
Why Blade Servers Still Don't Cut It, and How They Might

Intel Keeps Both Arms Swinging with Xeons, Jabs with Itanium

Microsoft Ponies Up Another $100 Million for Novell Linux

Mad Dog 21/21: Newtonian Economics

Two More Xeon-Based Galaxy Servers from Sun

Four Hundred Stuff
A Better Kind of OCR Promised by Brainware

Bug Busters Adds Remote Journaling to HA Offering

PARADE Magazine Turns a Page with ASNA's AVR and DataGate

Magic Updates RIA Framework with .NET Client

Infor Revives Infinium Brand for Casino Business

Big Iron
For Some Customers, the Mainframe Is Green

Top Mainframe Stories From Around the Web

Chats, Webinars, Seminars, Shows, and Other Happenings

System i PTF Guide
December 6, 2008: Volume 10, Number 49

November 29, 2008: Volume 10, Number 48

November 22, 2008: Volume 10, Number 47

November 15, 2008: Volume 10, Number 46

November 8, 2008: Volume 10, Number 45

November 1, 2008: Volume 10, Number 44

The Windows Observer
Citrix Addresses Performance with XenApp 5

Server Buyers Shop Like It's 1999 in the Second Quarter

Intel Keeps Both Arms Swinging with Xeons, Jabs with Itanium

Mad Dog 21/21: Newtonian Economics

Microsoft Does Something About Those SQL Injection Attacks

The Unix Guardian
What the Heck Is the Midrange, Anyway?

Overseas and Notebook Sales Offset Printer Declines for HP in Q3

Two More Xeon-Based Galaxy Servers from Sun

Mad Dog 21/21: Newtonian Economics

Intel's Nehalems to Star at IDF, AMD Pitches Shanghai

Four Hundred Monitor
Four Hundred Monitor's
Full iSeries Events Calendar

THIS ISSUE SPONSORED BY:

Profound Logic Software
WorksRight Software
Twin Data


Printer Friendly Version


TABLE OF CONTENTS
Four Ways to Avoid Problems Caused by Global Data

Where's the Service Program?

Admin Alert: The Dangers of User Profiles with Privileges

Four Hundred Guru

BACK ISSUES

From the IT Jungle Forums
Insert via Java

iSeries Access for Web

Mimix installation and configuration docs

EDI Inovis Programmer - Heavy Duty Problem Solver - Anytime

Data Queues vs. MQ Series: Performance

Removing blanks from a CL Variable

XML





 
Subscription Information:
You can unsubscribe, change your email address, or sign up for any of IT Jungle's free e-newsletters through our Web site at http://www.itjungle.com/sub/subscribe.html.

Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.
Guild Companies, Inc., 50 Park Terrace East, Suite 8F, New York, NY 10034

Privacy Statement