June 16, 2004 Dear Readers
As I mentioned in “Effective Messaging, IBM’s Way,” a reader named Vincent had some good ideas that are standards in his shop. All of them are simple, common-sense tips that can make life run a little smoother. I offer them to you for your consideration, along with a few comments and examples of my own that follow in italic type.
1. If you call QCMDEXC, use SNDPGMMSG MSGTYPE(*INFO) to display the command to be run in the job logs for later debugging.
The job log shows a call to QCMDEXC, but not the parameter values. Instead, there is a message that says, “The CALL command contains parameters.” The following example logs the parameters to the job log.
SNDPGMMSG MSG('Command: "' *CAT &CMD *CAT '"') CALL QCMDEXC (&CMD 80)
2. For all CL program calls, use SNDPGMMSG MSGTYPE(*INFO) to display the parameters in the job logs for later debugging.
This is a generalization of the previous tip. The job log shows calls to programs, but not the parameter values. The following example logs the parameters to the job log.
SNDPGMMSG MSG('Parms> File:' *BCAT &FILE *BCAT 'Lib:' + *BCAT &LIB) CALL SOMEPGM (&FILE &LIB)
3. Always put the program/query name in the header of all reports.
Don’t hard-code the program name, if you can avoid it. You can waste a lot of time before you figure out that the report that pretends to come from program XYZ was really produced by a clone of program XYZ.
RPG programs can get the program name from the first 10 positions of the Program Status Data Structure, which is also known as subfield *PROC. The following two code snippets are equivalent.
D sds D PgmName *proc D sds D PgmName 1 10
To learn how to make a CL program determine its own name, see “Make a CL Program or Module Retrieve Its Name.”
4. When a query generates a report, use the OVRPRTF file(QPQUPRFIL) SPLFNAME(xxx), where xxx is the query name. Optionally, use the USRDTA keyword to describe the report.
5. All reports should have a last line showing “end of report.”
This prevents users from guessing whether their reports completed. A reader named Andrew adds more information to the last line.
6. The RUNQRY command should always include all of the files used in the QRYFILE keyword, with either *LIBL or QTEMP as the library. This is so the program can be run in a testing library.
You can also override a database file that Query is building. Using the value *LIBL or QTEMP provides complete dependence on the library list, which is good for testing.
7. Do not use MULT 10000.0001 (or any variation thereof) to convert dates from CYMD to MDCY. This is a good trick, but it is a very inefficient date conversion method that does have a big effect on performance.
In spite of seeing this warning many times over the past 20 or so years, I still see plenty of code that uses this technique.
8. Do not hard-code any library name other than QTEMP.
This is a great idea, but to pull it off requires putting some thought into job descriptions.
9. Do not use DLTOVR(*ALL). You could accidentally delete overrides elsewhere in the job stream. Specify the overrides individually.
Better yet, don’t use overrides if you can put the information in a file description.
10. If a printer file is defined with anything other than the default page size, put the necessary values for the parameters of the Create Printer File (CRTPRTF) command in comments in the source code and create the printer file with those parameter values. Do not use the Override with Printer File (OVRPRTF) command in a CL procedure to change them. OVRPRTF should be used for changing output queue, USRDTA, PRTTXT, HOLD, SAVE, and number of copies.
Even if a printer file is not externally described, creating a printer file to hold settings such as page size and form type is a good idea.
11. If you have a program that remains open (indicator LR is *OFF), make sure that you close it when you’re finished or run the Reclaim Resource (RCLRSC) command.
My favorite way to handle this is to call the program with no parameters. The called program uses the %PARMS built-in function to determine the number of parameters passed to the program. If that value is zero, the program sets on LR and shuts down immediately.