• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • A Philosophically Engineered Approach to the Processing of Parameters

    April 18, 2012 Ted Holt

    Note: The code accompanying this article is available for download here.

    Too often we humans give little thought to what we do or why we do it, even though taking an organized approach to an activity has its advantages. In this article, I present one approach to the handling of parameters in programs and tell why I consider this a good way to process parameters.

    Parameters are data that are supplied to a program in order to affect the way it behaves. For example, the ability to supply file names, member names, and various options to the Copy File (CPYF) command allows me to use one program to copy any file instead of having to write a new program each time I want to copy a file.

    Through most of my programming career, I took the approach of not referencing a parameter until I needed it. I regret that I wrote many programs before I finally realized that there is a better way. I now advocate that each parameter be verified insofar as possible in the initialization stage.

    Before the program gets to the business of doing the work it was commissioned to do, it goes through three steps:

    1. Ensure that all required parameters were passed to the program.
    2. Supply default values to optional input and input-output parameters that were not passed to the program.
    3. Verify that the parameter values are acceptable.

    These three tasks are not as distinct as they may seem. The first two steps perform some data verification in the process of testing that a parameter was passed. Step three adds any other tests that need to occur.

    I use CL to illustrate this approach, but the principle applies equally to programs written in other languages.

    Suppose a program defines three input parameters: customer number; cutoff date; and sort sequence.

    pgm parm(&inCustNbr &inThruDate &inSortSeq)
    
    /* Parameters */
       dcl  &inCustNbr      *dec      (5 0)
       dcl  &inThruDate     *char      7        /* cyymmdd */
       dcl  &inSortSeq      *char      1
    

    All parameter names begin with “in”, my convention for input-only parameters. (I use “io” and “ou”, respectively, for input-output and output parameters.)

    Customer number is a required parameter in this illustrative application, while cutoff date and sort sequence are optional. The cutoff date (here called &inThruDate) defaults to a single, left-adjusted asterisk, which indicates that the program is to use the job date. The default sort sequence is ‘1’, which tells the system to sort on a certain set of fields, irrelevant to this discussion.

    To carry out these three tasks, I work from copies of the parameters.

    /* Copies of parameters */
       dcl  &CustNbr        *dec      (5 0)
       dcl  &ThruDate       *char      7
       dcl  &SortSeq        *char      1
    

    The copies of input and input-output parameters must be copied into the copies when the program begins execution. The copies of input-output and output parameters must be copied to any corresponding passed parameters before control returns to the caller. Except for these two times, the program uses the parameter copies, not the parameters themselves.

    I also use other working variables as needed.

    /* Other variables */
       dcl  &BadParm        *lgl
       dcl  &TestDate       *char      7
    

    The program sets variable &BadParm to true if any supplied parameter cannot be copied to the copy variable or if any parameter has an invalid value.

    I also use three messages from message file USRMSGF.

    ADDMSGD MSGID(USR8101) +
       MSGF(SOMELIB/USRMSGF) +
       MSG('Missing parameter &1.') +
       SECLVL('Parameter &1 is required. +
               You must supply a value to this program.') +
       SEV(30) +
       FMT((*CHAR 10))
    
    ADDMSGD MSGID(USR8102) +
       MSGF(SOMELIB/USRMSGF) +
       MSG('Invalid value for parameter &1.') +
       SECLVL('The value supplied to parameter &1 is invalid.') +
       SEV(30) +
       FMT((*CHAR 10))
    
    ADDMSGD MSGID(USR8109) +
       MSGF(SOMELIB/USRMSGF) +
       MSG('One or more parameters is in error. The program is canceled.') +
       SECLVL('Supply appropriate values for the parameters.') +
       SEV(40)
    

    Now consider the three steps in detail.

    Step one is to verify that all required parameters were passed to the program. The program does this by attempting to copy the required parameters to the copies.

    /* 1. Required parameters               */
    /* .... Customer number                 */
    
       chgvar   &CustNbr     &inCustNbr
       monmsg   mch3601   exec(do)
          sndpgmmsg   msgid(usr8101) msgf(usrmsgf) msgdta(CUSTNBR) +
             msgtype(*diag)
          chgvar   &BadParm    '1'
       enddo
       monmsg   (mch0000 cpf0000)  exec(do)
          sndpgmmsg   msgid(usr8102) msgf(usrmsgf) msgdta(CUSTNBR) +
             msgtype(*diag)
          chgvar   &BadParm    '1'
       enddo
    

    If the caller did not pass at least one parameter to the program, the CHGVAR command causes the system to send escape message MCH3601. The MONMSG command catches the exception and sends a diagnostic message to the caller, telling it which required parameter was not supplied and sets logical variable &BadParm to true.

    The second MONMSG command catches all other errors, the only likely one of which is that the parameter’s value could not be converted to a five-digit packed decimal value. The program sends a diagnostic message and sets logical variable &BadParm to true.

    Step two is to copy optional parameters to the copy variables. This step differs from the code for required parameters in one way. If a parameter is not supplied, the copy variable is loaded with a default value. Here’s the code for the cutoff date.

    /* 2. Optional parameters */
    /* .... Cutoff date                     */
    
       chgvar   &ThruDate    &inThruDate
       monmsg   mch3601   exec(do)
          chgvar   &ThruDate  '*'   /* default = use current date */
       enddo
       monmsg   (cpf0000 mch0000)   exec(do)
          sndpgmmsg   msgid(usr8102) msgf(usrmsgf) msgdta(THRUDATE) +
             msgtype(*diag)
          chgvar   &BadParm    '1'
       enddo
    

    If the caller passed two or more parameters, the program copies &inThruDate to &ThruDate. Otherwise, &ThruDate gets a single asterisk, which tells the program to use the job date.

    After step two is complete, all parameters have been copied into the copy variables. From this point on, use only the copies, not the parameters themselves, until control returns to the caller.

    The third step is to validate the values of all parameter copies. Here’s the validation code for cutoff date.

    /* From this point on, use the copies of the     */
    /* parameters and not the parameters themselves. */
    
    /* 3. Validate parameter values */
    
    /* .... Cutoff date                     */
    
       if (&ThruDate *eq '*') do
         rtvjoba cymddate(&ThruDate)
       enddo
       cvtdat date(&ThruDate) tovar(&TestDate) +
          fromfmt(*cymd) tofmt(*cymd) tosep(*none)
       monmsg cpf0555 exec(do)
          sndpgmmsg   msgid(usr8102) msgf(usrmsgf) msgdta(THRUDATE) +
             msgtype(*diag)
          chgvar   &BadParm    '1'
       enddo
    

    If the Convert Date (CVTDAT) command fails, the value of &ThruDate is invalid.

    When the three steps are complete, variable &BadParm will be true if any error was found. In this case, the program sends an escape message to cancel itself.

       if &BadParm then(goto Abend)
    
    . . . more code, executed if no bad parms . . .
    
    Abend:
       sndpgmmsg  msgid(usr8109) msgf(usrmsgf) msgtype(*escape)
    

    But if no parameter errors were found, the program continues to the task it was designed to do.

       call pgm1 parm(&CustNbr)
       call pgm2 parm(&CustNbr &ThruDate)
       call pgm3 parm(&SortSeq)
       call pgm4 parm(&CustNbr)
    
    /* normal ending */
       return
    

    Notice that the “meat” of the program uses the copy variables, not the parameters themselves.

    To see the program in its entirety, see the attached text file.

    What I most like about this parameter-processing approach is that many common errors are found before the job has had an opportunity to corrupt the database or waste processing time. It is possible that one of the called programs may have a problem with the value of a parameter, but the likelihood of that happening is reduced.



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

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Midrange Dynamics North America

    With MDRapid, you can drastically reduce application downtime from hours to minutes. Deploying database changes quickly, even for multi-million and multi-billion record files, MDRapid is easy to integrate into day-to-day operations, allowing change and innovation to be continuous while reducing major business risks.

    Learn more.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    ARCAD Software:  Change & Release Management: High time to move to a new standard. 4/25 Webinar
    BCD:  Presto instantly gives IBM i green screens a Web GUI. View a 2 minute video or try it FREE
    COMMON:  Join us at the 2012 Conference & Expo, May 6 - 9 in Anaheim, CA

    IT Jungle Store Top Book Picks

    BACK IN STOCK: Easy Steps to Internet Programming for System i: List Price, $49.95

    The iSeries Express Web Implementer's Guide: List Price, $49.95
    The iSeries Pocket Database Guide: List Price, $59
    The iSeries Pocket SQL Guide: List Price, $59
    The iSeries Pocket WebFacing Primer: List Price, $39
    Migrating to WebSphere Express for iSeries: List Price, $49
    Getting Started with WebSphere Express for iSeries: List Price, $49
    The All-Everything Operating System: List Price, $35
    The Best Joomla! Tutorial Ever!: List Price, $19.95

    IBM Buys Varicent for Cloud-Based Sales Performance Management AWS/400: Amazon Builds An AS/400-oid Cloud

    Leave a Reply Cancel reply

Volume 12, Number 10 -- April 18, 2012
THIS ISSUE SPONSORED BY:

Bug Busters Software Engineering
WorksRight Software
CNX

Table of Contents

  • A Philosophically Engineered Approach to the Processing of Parameters
  • Have Your Cake and Eat It, Too
  • Admin Alert: Planning An i 6.1 Upgrade

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24
  • Big Blue Raises IBM i License Transfer Fees, Other Prices
  • Keep The IBM i Youth Movement Going With More Training, Better Tools
  • Remain Begins Migrating DevOps Tools To VS Code
  • IBM Readies LTO-10 Tape Drives And Libraries
  • IBM i PTF Guide, Volume 27, Number 23

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle