You are on page 1of 6

HOME PUBLICATIONS NEWS BUYER\'S GUIDE EVENTS FORUMS VIDEOS Analysis Analysis of News Events Commentary l App Software

re Collaboration & Messaging Microsoft Customer Relationship Management Document Management Enterprise Resource Planning/Financial General Managed Services/SaaS l Career General l Case Studies Programming - RPG l Database Written by Robert Cozzi Business Intelligence Tuesday, 30 November 2004 18:00 DB2 Microsoft Access MySQL Procedures (or "subprocedures," as are they are called in RPG IV) are the fundamental building blocks l RPG IV applications. If you are not regularly using procedures in your RPG IV code, you are Internet of all Application Servers simply writing RPG III programs using RPG IV syntax. Being an RPG III programmer in RPG IV a bad thing clothing isn't Commerce to be, but you need to take that next step toward writing true RPG IV code. General To get to that point, you need to start using procedures. Procedures are a bit different from RPG's Portals traditional subroutines in that they are more than just a repeated section of code. Procedures are not a Protocols replacement for subroutines; instead, they are a different kind of technology whose capability overlaps Telephony the capability of subroutines. In other words, you can continue to write subroutines, but there is l Networking absolutely no compelling reason to do so. Everything you do with subroutines can be accomplished Emulation with procedures. General From a high-level perspective, procedures differ from subroutines as follows: Wireless/Mobile l Op Systems IBM i accept parameters just like programs do but with more optional features. l Procedures (OS/400, i5/OS) Linux/Open Source Subroutines do not accept parameters. Microsoft l Procedures can be used as an extension to the RPG IV language. In other words, you can createUNIX/AIX a procedure, such as TOUPPER, whose purpose in life is to convert lowercase to l Product Reviews then use that procedure within a conditional statement or on an assignment uppercase, and l Programming statement. You can't do that with subroutines. APIs l You can declare fields within procedures, and those fields will be isolated to the procedure. This Business Integration means that outside of the procedures, those fields do not exist; they are not known to the other Change mainline calcs procedures or Management in the program. Therefore, you can use more meaningful names for C L fields and other variables when they are declared within a procedure. (And that means work Dev Tools you can avoid using symbols such as #, @, and $ in field names!) General be compiled and stored separately from the program itself. You can actually l Procedures can createJava a source member that contains nothing but a few of your favorite procedures, compile it, RPG and then link to it at compile time, just as if the procedures were embedded in the main Scripting program itself. Subroutines, however, must always be declared in the source of the main SQL program. Visual Basic Web Languages These Security l few points are just the beginning of the advantages of procedures over subroutines. Compliance/Privacy General Building That First Procedure IBM i (OS/400, i5/OS) Microsoft Probably the most difficult step in using procedures is creating that first working procedure. To do this, l System Admin you need a couple of new statements in RPG IV that declare the procedure. Those statements are the General P specifications. Availability/Disaster Recovery High Performance Monitoring and end The P specifications declare the start & Tuning points of a procedure. You need two P specifications for l TechTips each procedure you create: one to indicate the start of the procedure code and one to indicate the end APIs of the procedure code. Career Think of the P specification of a procedure as the equivalent of the BEGSR and ENDSR opcodes. For CL example, to declare a subroutine named TOUPPER, you might have the following specified: Collaboration CSRToUpperBegsr Database Dev Tools **subroutinecodegoeshere Doc Mgmt HA/DR CSRendToUpperEndsr IBM i To declare Internet named TOUPPER, you would have the following code with P specifications a procedure instead of Java and ENDSR statements: BEGSR Linux PToUpperB Microsoft Networking //procedurecodegoeshere Programming RPG PToUpperE Scripting Security OK, the difficult part is over. Now, you need to migrate your subroutine-writing skills to procedure To writing skills.SQLdo this, you first need to have an example subroutine that you want to migrate to a Sys Admin procedure. Illustrated below is the example RPG IV source code that uses work fields and a subroutine to convert Web Languages lowercase to uppercase. Granted, I could have just call the XLATE opcode and avoided the call to the subroutine altogether, but I needed something to illustrate this example. DUPPERC'ABCDEFGHIJKLMNOPQRSTUVWXYZ' DlowerC'abcdefghijklmnopqrstuvwxyz' DTU_WorkS1024AVarying
l l l l l l l l

Username

Login

c d e f g Remember me Forgot login?|Register


FOLLOW US

Let's Build a Procedure

MOST POPULAR

ARTICLES
l l l l l l l l l l

Practical RPG: The Future of RPG What You Need to Know to Convert Spooled Files to PDF (and More)! Don't Be Misled by SETLL *LOVAL How to Create, Compile, and Use Service Programs Practical SQL: Three Ways to JOIN Partner TechTip: Our System Administrator Did WHAT? TechTip: Pie Charts: Generate Professional-Grade Charts in Your Programs in Real Time, Part 1 Cool Things: Free, Open-Source TN5250J Cool Things: SQL Functions and List APIs Using Binding Language with Your Service Programs

BOOKS

Top 10 Best-Selling Titles


1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Subfiles in Free-Format RPG Control Language Programming for IBM i Programming in RPG IV Advanced, Integrated RPG Mastering IBM i IBM System i APIs at Work RPG TnT The IBM i Programmer's Guide to PHP The Modern RPG IV Language IBM System i APIs at Work

FORUMS
1. 2. 3. 4. 5. I need to transfer a spool file(i.e. compile listing) to a PC file for editing(2191views) Batch file in as400(1746views) Trigger bombing on program library(1477views) Zip/Unzip now, don't wait for 7.1(1132views) PHFA - 2 new Software Developer positions available (IBM i RPG ILE/Microsoft Dotnet)(828 views) The International Freedom of Expression Forum(721views) A6005004 - Can't find console(589views) jQuery plugin for Fixed Header Tables(393views) Fixed-Header plugin now available in CGI_WRKDBF(185views)

6. 7. 8. 9.

Dwork1S1024AVarying Dwork2S1024AVarying CCustNoChainCustRec CIf%Found() CmoveCSTNAMETU_WORK CexsrToUpper CmoveTU_WORKWork1 CmoveOLDNAMETU_Work CexsrToUpper CmoveTU_WORKWork2 CifWork1=Work2

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 1 / 6

**Old/Newnamesareidentical... Cendif Cendif CSRToUpperBegsr C Clower:UPPERXLateTU_WorkTU_Work CSRendToUpperEndsr In this example, a customer record is retrieved from the customer master file, and the CSTNAME field from that file is going to be compared to the previous value for that field. This allows you to verify whether or not the name of the customer has changed yet ignore the upper/lowercase differences between the two fields. Now, rewrite this using RPG IV syntax. First, create just the procedure itself, without changing any of the mainline calc's logic. Here is a fundamental version of the TOUPPER subroutine, written as a procedure. PToUpperB DToUpperPI Clower:UPPERXLateTU_WorkTU_Work Creturn PToUpperE You need to add three lines of code to the TOUPPER procedure to make it a functioning component. The D specification that immediately follows the P specification is used to identify the procedure equivalent of the *ENTRY PLIST. In other words, this declares the parameter list for the procedure. This is known as the "procedure interface." So remember, the term "procedure interface" means "the procedure's *ENTRY PLIST." Since you're not using parameters at this point, you specify an empty procedure interface. Now, you need to go into your existing code and change it so that the procedure is called instead of the subroutine. There are three ways to call a procedure, which may be why some people get confused (too many options), but they're easy to get used to. These are the three ways to call a procedure:
l l l

Using the CALLB opcode Using the CALLP opcode Implicitly, by specifying the procedure within an expression

For now, you simply want to have a plug-in replacement for the subroutine call, so replace the call to the TOUPPER subroutine with a CALLB to the TOUPPER procedure. Here's the completed code: CCustNoChainCustRec CIf%Found() CmoveCSTNAMETU_WORK CCALLB'TOUPPER' CmoveTU_WORKWork1 CmoveOLDNAMETU_Work CCALLB'TOUPPER' CmoveTU_WORKWork2 CifWork1=Work2 **Old/Newnamesareidentical... Cendif Cendif In the example above, the EXSR statements have been replaced with CALLB statements. Note that, in RPG IV, the compiler converts procedure names to uppercase by default. Therefore, when you call a procedure, the procedure name must be in uppercase; otherwise, the compiler will not locate it. If you had specified the CALLB statement like the following, the compile would have failed: CCALLB'ToUpper' Now you've created a procedure that can replace the old subroutine, but so what? What advantage does this procedure have over the subroutine call? The answer to this question is simply maintainability. People say 80% of all programming is maintenance programming. Making changes means working with existing code. If you can reduce the number of lines of code that have to be fiddled around with and isolate those lines of code, you can increase programmer productivity. For example, suppose you want to avoid using the work fields in these examples. You can easily do that with the TOUPPER procedure without concern for the field names of any other fields (work fields or otherwise) in the program source. Let's look at a slightly different version of the TOUPPER procedure. This one avoids the use of work fields and instead takes advantage of the parameter capability of procedures.
0001PToUpperB
0002DToUpperPI1024AVarying 0003Dinput1024AVaryingCONST 0004DUPPERC'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 0005Dlowerc'abcdefghijklmnopqrstuvwxyz' 0006DoutputS1024AVarying 0007Clower:UPPERXLateInputOutput 0008CreturnOutput

0009PToUpperE

In this updated version of the TOUPPER procedure, I've made the following changes:
l l l l l

Added a parameter named INPUT Added a field named OUTPUT Specified a return value for the procedure Moved the named constants UPPER and LOWER to the procedure Returned the OUTPUT field to the caller

To add parameters to procedures, you simply specify the parameter name, its type, and its length, which is virtually identical to declaring a subfield of a data structure. In fact, using procedure parameter lists is very similar to declaring data structures. In addition, you can specify that the parameter is not going to be changed by the procedure; to do this, add the CONST keyword to the parameter's description (see line 3). Making procedure parameters CONST helps to improve performance when calling the procedure; of course, the downside is that you cannot change the value of CONST parameters from within the procedure.

Return Value
Procedures, like programs, allow you to modify the value of any parameter passed into them (provided, as I mentioned, that the parameter does not contain the CONST keyword). This works essentially the same way that passing parameters to programs works.

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 2 / 6

Procedures have one more capability, however. Procedures can return a value to the caller without going through a parameter variable. This capability classifies the procedure as a function instead of a procedure, but in RPG IV, we use the term "procedure" generically to mean both procedure and function. When a procedure is a function, its return value may be used within an expression (a conditional statement or an EVAL operation). For example, since the TOUPPER procedure returns a value, you can use it as follows:

CevalWork1=TOUPPER(CSTNAME)
Or, better yet, like this: CifTOUPPER(CSTNAME)=TOUPPER(OLDNAME) This method not only greatly simplifies the code, but also isolates the original 10-line routine into a single statement. Let's look at how this TOUPPER procedure would be called compared to the TOUPPER subroutine by rewriting the original code as follows: CCustNoChainCustRec CIf%Found() CifTOUPPER(CSTNAME)=TOUPPER(OLDNAME) **Old/Newnamesareidentical... Cendif Cendif This is much cleaner and easier to read and maintain. A maintenance programmer will appreciate all the clutter of those work fields being eliminated.

One Final Component


Procedures, while easier to maintain than other methods do have one confusing element, prototypes. Prototypes are the single biggest source of confusion for RPG IV programmers when they attempt to move to procedures. Simply put, prototypes are required when using procedures. The compiler uses the prototype source code to syntax check calls made to the procedure to make sure the number of parameters and their data types exactly match what the procedure is expecting. So in our example, if you specified TOUPPER(12345), you would get a compile-time error message. Try that with a subroutine! The easiest way to use prototypes is to just accept the fact that the compiler requires them and create them by copying the procedure interface code. To create a prototype, simply copy the entry parameter list for your procedure, including the PI line and all parameter fields, to another location within the source member. Then, go to the letters "PI" in columns 24 and 25 of that PI line and change them to "PR" (meaning prototype). Here is the prototype source for the TOUPPER procedure: 0002DToUpperPR1024AVarying 0003Dinput1024AVaryingCONST From the source statement sequence numbers, you should be able to tell that I simply copied the procedure interface code from the procedure definition to create this prototype. I then changed the letters "PI" (procedure interface) to "PR" (prototype). This source code must be at the top of the source member with the regular D specifications (above the mainline calcs). For completeness, I want to illustrate the entire original subroutine method rewritten for procedures:
0001HDFTACTGRP(*NO) 0002FCUSTMASTUFEKDISKPREFIX('CM.') 0003FCUSTEDITCFEWORKSTN 0004DToUpperPR1024AVarying 0005Dinput1024AVaryingCONST 0006DCMEDSExtname(CUSTMAST)QUALIFIED 0007DOLDNAMESLike(CM.CSTNAME) 0008CCustNoChainCustRec 0009CIf%Found() 0010CifToUpper(CM.CSTNAME)=ToUpper(OLDNAME) **Old/Newnamesareidentical... 0011Cendif 0012Cendif

0013PToUpperB 0014DToUpperPI1024AVarying 0015Dinput1024AVaryingCONST 0016DUPPERC'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 0017Dlowerc'abcdefghijklmnopqrstuvwxyz' 0018DoutputS1024AVarying 0019Clower:UPPERXLateInputOutput 0020CreturnOutput 0021PToUpperE

In the example above, the field CM.CSTNAME from the customer master file is compared with the field OLDNAME (line 10). The TOUPPER procedure is called twice in one statement, and its return value is what is being compared. Since this procedure uses variable-length fields, the original value's length is also the length of the data that is returned by the procedure.

Just Do It
Procedures are different; they look different and are coded differently. But they are not and should not be scary. Nor should they be avoided. The use of procedures will lead you down a path of easier program maintenance and much greater flexibility than previously available. While you do not need to convert existing subroutines into procedures, you should start writing all new maintained code using procedures whenever the situation calls for a subroutine. Bob Cozzi is a programmer/consultant, writer/author, and software developer. His popular RPG xTools add-on subprocedure library for RPG IV is fast becoming a standard with RPG developers. His book The Modern RPG Language has been the most widely used RPG programming book for more than a decade. He, along with others, speaks at and produces the highly popular RPG World conference for RPG programmers.

About the Author:


Bob Cozzi is a programmer/consultant, writer/author, and software developer of the RPG xTools, a popular add-on subprocedure library for RPG IV. His book The Modern

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 3 / 6

RPG Language has been the most widely used RPG programming book for nearly two decades. Robert Cozzi

MC Press books written by Bob Cozzi available now on the MC Press Bookstore. RPG TnT Jam-packed with an unbelievable number of quick, easyto-implement RPG tips! List Price $65.00 Now On Sale

The Modern RPG IV Language Cozzi on everything RPG! What more could you want? List Price $99.95 Now On Sale

Read More >>

Articles by this Author: Create an Auto-Extend User Space View all articles by this author < Prev Next >

Last Updated on Tuesday, 30 November 2004 18:00

MC Press Web Site Staff This is a discussion about [B>Let\'s Build a Procedure[/b>. Click here for the article. avrahamn@coop.co.il Now in this example You gave, instead of 3 lines of code, more than a dozen lines were used. Besides that, it cannot be compiled with the regular compilation - CRTBNDRPG. It needs to have CRTRPGMOD and binding afterwards. If wee need it for reusability of code, anyway it is not so easy to use, Every program that calls it need to have a prototype. I am aware that we could use a /copy compile directive. but that takes us to the old system 36 days where the only way to make reusable code is by having /Copy directives of AUTO REPORT. Also the linking and binding technics take us to the old days old SYSTEM36 with the Linkage Editor. All this may be good for PC users that did not taste the ease of use of just a plain CALL-PARM statement. We - AS400 Users that got used to the simplicity of CALL-PARM, for us it is step backwards. As for speed, anyway must of the heavy usage is on file openning etc. I made a test of Bound module with one file to open and almost did not find any diference Between CALL and CALLB. The big diference was when i changed to end the program with RETURN instead of *INLR. I am expecting from IBM the following changes in order to make the use of procedures really more productive: 1. Not needed to code the Prototye twice. The calling program should find it from the called procedure. 2. On CALLB - find the module in the Library list. No need the extra coding of binding directory ETC. 3. On a regular program, there is an option to create a command, and then use it with the Command Interface that is so vital when calling programs with many parameters. Imagine the so popular used command CPYF, if we would need to use it like a procedure an count which parameter we are on. 4. Same as with User Defined Commands, F4 on SEU prompts us for its parameters, similar to it we should be able to do with user defined procedures. Guest.Visitor Hi, I would like to "cut my teeth" on an easy procedure. I have in mind a procedure to take separate address fields (street, city, state, zip, country) and string them together into the typical address for an envelope. I think with the example in the article I can write the procedure and call it from the program. But can you take it one step further do I compile it, and then I think I have heard about binding etc... Of course this has probably been covered lots of times and in lots of places. But I appreciate the simplistic, low level, of the article, so please continue... joelcochran There is nothing wrong with using /copy for prototypes. We aren\'t talking about program logic here, so you don\'t really have the pitfalls that originally had programmers running away from /copy. Also, the fact that you used to do something similar on the 36 does not make it a bad approach today. Not writing external procedures because you have to compile them with a different command is just silly! And what makes "CRTBNDRPG" the "regular" way? If it bothers you that much, compile EVERYTHING with CRTRPGMOD and then use the CRTPGM command. At least this way, you only have to fiddle with one approach. And binding is hardly difficult, it\'s just different than traditional RPGIII. Obviously, I disagree that making it reusable is different. I think it is very easy, and if you aren\'t doing it, you are selling your RPG skills short. Now, for your expected "improvements": 1. I kind of agree here: the procedure could match the calling prototype to the PI statement. But in all honesty, this is not a big deal. And by forcing me to have the prototype in the procedure also, I know that I\'ve already created it appropriately so that it can be used in calling procedures. 2. Modules are not executable. Binding is at the heart of ILE, so you really can\'t avoid it. The exception is putting a *MODULE directly in a binding directory, which has a number of flaws of its own and not a practice I would recommend. Second, binding directories, while they are SUPER, are completely optional. So basically, if you don\'t like the "extra" coding for them (which is minimal), then don\'t use them. But that means opening a maintenance nightmare of binding by copy every module you reference in your program... for EVERY program. This approach would make ANYONE dislike ILE. 3. Again, what\'s a regular program? I\'m not sure what you are getting at here... 4. Now you are talking tools, not environment. This is the kind of thing that VisualStudio adds for Windows development. It has nothing to do with the language itself or program construction. I don\'t usually respond to this kind of stuff, but postings like this tend to discourage people from experimenting and learning ILE, and in this case that is unjustified. Are there some new things to learn with ILE? Of course. Is it different than "the way we\'ve always done it?" Absolutely. Is ANY of this a reason to naysay ILE? NO! And this is NOT a step backwards. This has nothing to do with "PC Users" vs. "AS/400". CALL-PARM was great, but limited. You can do everything you did with CALL-PARM and much more, and in a safer more productive manner using ILE enhancements. Joel Cochran http://www.rpgnext.com joelcochran This is a big question, so my response will be far from all inclusive, but here goes: Basically, you create *MODULE objects and the "bind" them together using the CRTRPGMOD command. In this case one for the calling program and one for the procedure. This binding occurs when you run the CRTPGM command. There are two kinds of Binding: 1) Bind by Copy. In

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 4 / 6

this approach, you reference the *MODULEs in the CRTPGM command\'s MODULE attribute. All of these *MODULEs are then COPIED into the *PGM object. This makes larger programs, and if the same one is copied over and over and over, it creates a maintenance headache should ou ever need to change a *MODULE. 2) Bind by Refernce. In this approach, you include a reference to the object you wold like the program to use at run time. This refernce is either a *SRVPGM using the BNDSRVPGM attribute of the CRTPGM command, or is contained in a *BNDDIR and referenced using the BNDDIR attribute. A binding directory is a just a listing of references. This approach is much easier to maintain in the long run, and since the objects are not copied into the *PGM, the programs are smaller. I would recommend learning how to create service programs to hold your *MODULEs, and then listing that *SRVPGM in a binding directory. Now you can reference the binding directory in your RPGIV code by adding an H-Spec like: h bnddir("MYLIB/MYDIR") Now you don\'t even have to reference it on the CRTPGM command. Joel Cochran http://www.rpgnext.com miller_ste Code the procedure in an RPGLE source member as shown in the example. Be sure to code an H spec H NOMAIN at the beginning of your source member. Compile the member using option 15 CRTRPGMOD. In order to call the procedure, you must bind it to a program that will call the procedure using CALLB, CALLP, or using an EVAL statement. You can also call a procedure from a CLLE (CL ILE Program) using CALLPRC PRC(Procedurename) PARM(input)RTNVAL(procedurereturn parameter). Here the RTNVAL parameter will accept what is passed back from the procedure. Good Luck! miller_ste I agree with Joel. Procedures are very useful for functions and logic that can be used over and over again from different programs/applications. The easiest way to code the Procedure Interface is with the /COPY. This allows you to code the PI in one place and replicate it wherever you need it. In fact with a combination of /IF /DEFINE /UNDEFINE you can make your source code very clean. Forget the S36 we are on the iSeries now and it is a very different environment. I can think of several functions that can be coded as a procedure that will work in most businesses Get Price, Get Tax, Get Rate, etc. If you are coding these over and over again in subroutines and I know many programmers are, you are missing the point. Don\'t forget, you can execute a procedure from a CLLE program too! Why are RPG programmers so reluctant to use procedures? They have been around for about ten years now. By now we should be beyond procedures and digging into free form RPG, other languages, and systems. Change is hard, but not changing is paralyzing. Is your boss going to accept from you that you can not do it? No, he will find someone else who can. R.Cozzi Comparing CALL and CALLB is a typical mistake most RPG programmers make. The reason they do this is because IBM foolishly tried to get people to use CALLB in place of CALL before RPG IV even had subprocedures. That was just stupid. The bulk of the overhead of a CALL is in the RPG Cycle start-up routine. So if you simply replace a CALL with a CALLB and compile the second RPG IV program as a module, you save nothing substantial and you add the complexity of CRTRPGMOD as avrahamn stated. I never advocate doing this kind of thing; in fact I will be an ass about it to the point where I would say if anyone tells you to do it that way, they don\'t know what they\'re talking about. You can use CRTBNDRPG with procdures, you just have to change the DFTACTGRP(*YES) parameter to DFTACTGRP(*NO) and it works fine. I use it everyday. If you modularize you code (multiple modules, then you use PDM option 15, CRTRPGMOD for the secondary modules and then use options 14, CRTBNDRPG with DFTACTGRP(*NO) and a binding directory. It is not difficult, it is just new and different. There are things that make it difficult, but you can ignore all that stuff if you want. Trying to do too much too soon will lead to accidents and some people are put off by accidents. Others, see them as learning experiences. You can never go to the Moon if you\'re affraid of making a mistake here and there. Ralph Daugherty An excellent article and discussion. I don\'t think the trasformation from subroutine to procedure could have been more dramatically clearer. rd avrahamn@coop.co.il I am still puzzled how do I know in which service program or module is the procedure. Lets say a program has in itself 5 service programs and 15 modules. When I see the name of any given procedure how do I know in which service program is that procedure and where is the source of it. After all that we need to say to IBM that our time is very valuable and before we will accept their innovations, they need to make it as easy to use as what is was in the old way and even easier. Also I need to have a command which is a must for any program with many parameters, and I cannot do it with a procedure. avrahamn@coop.co.il Is your boss going to accept from you that you can not do it? My buss Know that I can do it and even much more. The only question is if it pays to do. Is it better than before. I need a real comparison of all the benefits of CALL commands, all the disadvantages, and compare it to Prototype-Procedure-Module-Service Program. One day IBM may come to us and announce that they discovered something new: There is no need any more for all those extra steps of binding and prototyping. just use CALL-PARM, and You could even use keyword names instead of parameters just by position (COMMANDS). buck.calabro@commsoft.net > Now in this example You gave, instead of 3 lines > of code, more than a dozen lines were used. Judging the quality of code by it\'s line count is dangerous and misleading. Take the two snippets below. Which is better code? if a(x)=\'end\' ... endif if x>%size(a) ... else if a(x)=\'end\' ... endif endif --buck buck.calabro@commsoft.net > One day IBM may come to us and announce > that they discovered something new: There > is no need any more for all those extra steps > of binding and prototyping. just use CALL-PARM, > and You could even use keyword names instead > of parameters just by position (COMMANDS). I do this all the time, in addition to using subprocedures. buck.calabro@commsoft.net > I am still puzzled how do I know in which > service program or module is the procedure. Your source control system tells you. > When I see the name of any given procedure > how do I know in which service program is > that procedure and where is the source of it. When you see the name of a program how do you know which library it is in, and where the source is? > Also I need to have a command which is a > must for any program with many parameters, > and I cannot do it with a procedure. From a design perspective, a subprocedure should be thought of like a function. It is closer to SQRT than it is to an entire program. The CPP would call several functions (which are the subprocedures). If a subprocedure has many parameters, it is probably too big. --buck Ralph Daugherty I disagree with that particular advice, buck. Too many IT people push itsy bitsy functions, code only the size of the screen, and other programmer oriented constraints on usefulness of code. Examples are always pathetic and usually a freakin formula or something, with one return parm and not even a nod to reality. My short suggestion is that a subprocedure should be more like a small standalone program that we would write under RPGIII without setting *INLR on, and an input parm code to close, etc., that we have used in place of subprocedures and especially a separate module subprocedure that we would bind to a program or service program. I think the subprocedure as BIF is is also good, although I\'ve never written anything in BIF form, but not limited to that. That\'s just a thought ot two coming from the approach of the questions of the poster. Thanks for your insights as always, buck. rd buck.calabro@commsoft.net Hi Ralph! > I disagree with that particular advice, buck. Not a problem - that\'s why we have discussion lists! : many IT people push itsy bitsy functions, > code only the size of the screen, and other > programmer oriented constraints on usefulness of code. You\'ve hit the nail exactly on the head here. Generally the point of these limitations on the programmer are there because the programmer can\'t hold the whole thing in his head at once. There is genuine room for disagreement on exactly how big is \'too big\' and how small is \'too small.\' In general though, I find that large parameter lists are a red flag in the \'too big\' direction. For most of us RPGers, we\'re accustomed to very large programs, and many small units seem overly difficult to manage, so we stick to larger code units rather than smaller. > Examples are always pathetic and usually a > freakin formula or something, with one return > parm and not even a nod to reality. It\'s true that examples are usually off the wall, but that is not the fault of the concept me, the true value of subroutines is measured by the way the programmer\'s thinking shifts from large, amorphous blocks to smaller, concise functions. If you look at the way the rest of the programming industry writes code, you\'ll find that many small-ish functions is the way things have shaken out over 20 years ago. Everything from small 1 or 2 screen programs to mammoth applications like the Social Security system are written this way. On the other hand, if your shop has a good set of practices in place to do this sort of thing with a small program (no LR, call it one last time to shut down, naming conventions for the scratch variables to hold the results) then I say Bravo! Because you\'re already reaping the

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 5 / 6

benefits of reasonably small code blocks and thinking in terms of functions. --buck Ralph Daugherty [i>To me, the true value of subroutines is measured by the way the programmer\'s thinking shifts from large, amorphous blocks to smaller, concise functions. If you look at the way the rest of the programming industry writes code, you\'ll find that many small-ish functions is the way things have shaken out over 20 years ago. Everything from small 1 or 2 screen programs to mammoth applications like the Social Security system are written this way. On the other hand, if your shop has a good set of practices in place to do this sort of thing with a small program (no LR, call it one last time to shut down, naming conventions for the scratch variables to hold the results) then I say Bravo! Because you\'re already reaping the benefits of reasonably small code blocks and thinking in terms of functions. --buck [/i> I agree, buck. The concepts can be applied to RPG/400 as well, and are in well written systems. I think the large parm list as indicator of an out of control scope for a function, routine, method, standalone program, etc. is right on. Scope should be reasonable and useful and general enough to be used as building blocks to use again and again. For the poster, prototyped parm subprocedures with local variables enforce and type check the modularity and should be the norm, not something that is hard to figure out when to use. rd avrahamn@coop.co.il One big advantage of using commands vs. positional prameters is standarization. For example: prameter LVLCHK() is used on many IBM Commands (CRTPF, CHGPF, CRTLF, CHGLF, Etc.). When we see the parameter LVLCHK we know right away what the meaning is. If we would have to call that same routine vs an API bound or unbound call, we would not know the meaning of each parameter. More about the great advantage of commands The least IBM could do for us is to extend the procedures to allow refer to them via a command type interface, or to allow the creation of commands on the top of a procedure. buck.calabro@commsoft.net I guess my suggestion is to submit a Design Change Request. A link to the DCR can be had in the FAQ at http://faq.midrange.com --buck Guest.Visitor Hi all. I need some expert advice on procdures. From what I have read we have to have a PI statment in a (sub) procedure and a PR statement with the same parms in the calling program (Main procedure?) I have also seen suggestion to use /Copy to replicate these in the code. My question is this: If I create a member to be used by the /Copy that only has the parameters listed, no PI or PR line in it. Then can I code just a PR line in the main procedure followed by /Copy to get the parms in there and in the subprocedure just code a PI line followed by the /Copy? I would like to do this so if the parms should change for any reason I can just change them in the copy member and recompile anything using them instead of having to go into each procedure and change them. I am new to procedures so it is all still a little fuzzy to me but this seems to make sense from a maintenance standpoint. buck.calabro@commsoft.net > From what I have read we have to have a PI statment > in a (sub)procedure and a PR statement with the same > parms in the calling program (Main procedure?) Yes, exactly. The PI designates the code that implements the procedure and the PR designates the prototype so that the compiler can match up your use of the procedure with it\'s definition. The reason for the separate PR is that you might have the PI in a service program (which you don\'t have the source code for), and then the compiler can\'t know the proper definition. More or less. > I have also seen suggestion to use /Copy to > replicate these in the code. Here, \'these\' means the PR specs. > My question is this: If I create a member to be > used by the /Copy that only has the parameters > listed, no PI or PR line in it. Then can I code > just a PR line in the main procedure followed > by /Copy to get the parms in there and in the > subprocedure just code a PI line followed by > the /Copy? Sure, but that doesn\'t save you much effort, and it divorces the parameter list from the procedure name and return value. As in, what procedure do these parameters belong to? d inpPath * const d inpCCSID 5a const > I would like to do this so if the parms should change > for any reason I can just change them in the copy member > and recompile anything using them instead of having to > go into each procedure and change them. Yes, this is exactly right. If you find that you have the PI code in the same program as the PR code, then you probably want to consider using a service program instead of embedding the procedure many times into multiple source members. From a slightly different perspective, you probably shouldn\'t be changing the paramater list too often, unless it\'s to add new *NOPASS parameters at the end. If you change already-deployed procedures, you need to be very careful to get them all, or you\'ll be supporting multiple versions of them, which is generally undesirable. Normally, I\'ll create a new one if the parameter list has to change in the middle... Hope this helps. --buck mikespec [size="1">Code[/size> Please login to make comments.

User Rating:

/0

Poor n n n n n Best Rate j j j j j k k k k k l l l l l m m m m m i

Related Articles:
l l l l l

07/06/2011 09/16/2009 07/15/2009 07/15/2009 06/17/2009

Practical RPG: The Future of RPG Retrieving the Directory Contents of an FTP Server from Within RPG Use a Logical File Layer to Minimize Recompiles from Field Additions Use String Manipulation Built-In Functions to Process External Files Reusing a Single File Description on Multiple Files

MC-STORE.COM

Home | Publications | News | Events | Buyer's Guide | Forums | Videos | Popular | Archive | Bookstore Copyright 2012 MC Press Online, LLC | Privacy Policy | Search | RSS | FAQ | Contact Us | Write For Us|Editorial Review Board|Advertise | Site Map

http://www.mcpressonline.com/programming/rpg/lets-build-a-procedure.html

Page 6 / 6