Adaptable Data Areas
November 2, 2011 Ted Holt
If you’ve worked in IT for more than 15 minutes, you’ve undoubtedly been asked, “How hard would it be to. . . ?” The people who depend on the systems we support are constantly thinking of new and better ways to make information systems more closely resemble the reality of business. Every little thing you can do to ease the effort to modify software is worth doing. Here are two extremely simple ways to reduce the amount of effort required to change the length of a character data area.
Consider a data area, FacInfo (Facility Info), that contains one item of information: a four-character facility ID. A CL program that uses the data area might include source statements like those in the next piece of code.
dcl &FacID *char rtvdtaara dtaara(FacInfo) rtnvar(&FacID)
This is how programmers typically define and access character data areas, and this code works fine day in and day out.
One day, a local panjandrum asks you, “How hard would it be to add the facility location to these and other reports?” You know that the size of the data area must be increased. Your answer to him depends on how your CL and RPG programs define the data area.
If your CL programs access the data as shown in the first bit of code above, then you or some other human being must change the source code. The Retrieve Data Area (RTVDTAARA) command in that code is equivalent to the command in this next piece:
rtvdtaara dtaara(FacInfo *all) rtnvar(&FacID)
By default, RTVDTAARA accesses the entire contents of a data area. The special value *ALL in the second positional parameter of the DTAARA keyword tells the system to copy the entire data area into the &FACID variable. If the size of the data area does not match the CL return variable, the system issues escape message CPF0811 (RTNVAR parameter has incorrect length for data area.)
The better way to code RTVDTAARA is to specify the beginning position and data length instead of *ALL, as shown here:
rtvdtaara dtaara(FacInfo (1 4)) rtnvar(&FacID)
Specify beginning position and length when retrieving a data area. This code will continue to run correctly, without having to be changed or recompiled, when the data area length changes. If all your CL programs use this method to define the FacInfo data area, you only have to change the programs that need the newly added data.
RPG programs face their own challenges when working with data areas. This next piece of code shows how a programmer might define the Facility ID parameter:
D FacilityInfo ds 4 dtaara(FacInfo) D FacilityID 4 /free in FacilityInfo;
This code typifies data area definition and access in RPG. If you modify the length of the data area, but do not recompile the program, the system will issue escape message RNX0411. (Data area SOMELIB/FACINFO type or length does not match program data area *LIBL/FACINFO.) Secondary text is even more specific: “Data area *LIBL/FACINFO was defined in the RPG procedure to be of type *CHAR and length 4.” The actual data area SOMELIB/FACINFO is of type *CHAR and length 20. If a *LGL data area is expected, a data area of type *CHAR and length 1 is also allowed.)
A better way is to define the data area externally, as demonstrated below:
// File: QRPGLESRC // Member: FACINFO // Purpose: external definition of data area FACINFO D FacilityInfo ds 20 dtaara(FacInfo) D FacilityID 4 D FacilityLoc 16
Data areas can be externally described in copybook members.
Programs that access FACINFO do so as shown here:
/copy qrpglesrc,facinfo /free in FacilityInfo;
RPG programs easily access externally defined data structures. The result is that RPG programs must be recompiled after the data area is resized, but they do not have to be edited.
These simple tips are good examples of what Alan M. Davis wrote in 201 Principles of Software Development. Principle 74, Design for Change, includes the following wisdom: “. . .you must select architectures, components, and specification techniques to accommodate major and incessant change.”
The word “incessant” describes my world. What about yours?