Development Environments
May 12, 2010 Paul Tuohy
It happens at every conference I speak at. Over a cup of coffee (or other liquid refreshment) someone will ask me about my development environment.
So, if for no other reason than allowing me to answer with: “you can read about it at IT Jungle,” here is a description of my current development environment for a little System i Developer application I’m working on. But First Of course, your development environment may well be dictated by a change management system. I am not working under those conditions (the joy of being a one-man development team), which gives me more flexibility in how I chop and change things. It goes without saying that if there are two or more of you working on an application, you should be using a change management system–especially in an ILE environment. Development Tools Primarily, I make use of System i Navigator and RSE for native environment development. For RSE, I alternate between WDSC and RDi. I use Zend Studio for PHP development, and I also use Zend Studio for most of my HTML, Javascript, and CSS development. Since I use Linux for my desktop (I have Windows XP running in a virtual machine for Navigator and WDSC/RDi), I use tn5050j as my 5250 emulator and I also make use of RPG Next Gen when I need to make a very quick change and don’t have time to fire up Windows in the virtual machine. The Libraries I usually have three libraries: program objects, source, and database. My current application consists of the libraries: SIDMAINTV2, SIDSRCV2, and SIDDBV2.
The Source Library The source library contains a number of source physical files and binding directories. Code 1 shows a list of the source physical files and binding directories in the SIDSRCV2 library.
Code 1--Contents of the SIDSRCV:
Source Files
COMMON Common Application Functions
FILEPROCS File Procedures
GENSTAT Programs to Generate Static Documents
PHPFUNC Functions especially for PHP
REGFUNC Online Registration Routines
SIDSRC SiD Maintenance Programs
UTILITY Utilities
Binding Directories
COMMON Binding for Common Routines
FILEPROCS Bindings for File Procedures Service
PHPFUNC Bindings for PHP Functions
REGFUNC Binding for Registration Service Programs
SIDBNDDIR Binding for SiD Maintenance Application
UTILITY Binding for Utility Service Program
Each source file contains sets of related source members. Related source members may be for a function within the application (e.g., GENSTAT contains source for programs used to generate static HTML documents and Excel spreadsheets), or may relate to the sources for a Service program (in Code 1, all the other source files except SIDSRC and GENSTAT are for service programs). Source files for application functions are fairly straightforward and simply contain the source of programs for compilation. On the rare occasion where I might have a multi-module program, I will create a separate source physical file for the program. Hand-in-hand with the application source files is an application binding directory (SIDBNDDIR in Code 1). But let me come back to this after I have discussed service programs. Access to all source is simply set up in RSE by creating a filter for all source physical files in the source library (shown later in Figure 3). Service Programs These are the conventions I use for service programs. (An example follows.)
Code 2--Contents of STDHSPEC in UTILITY:
H noMain debug option(*srcstmt : *nodebugio)
H bndDir('UTILITY' : 'QC2LE')
Let’s look at an example. Figure 1 shows the RSE filter for the SIDSRCV2 library including the contents of the REGFUNC source physical file.
These are the main points to note:
Code 3--Contents of the PREGFUNC source member:
/include regfunc,pRegF01A
/include regfunc,pRegF02A
/include regfunc,pRegF03A
/include regfunc,pRegF04A
The Binder Language Member How this works will depend very much on how you manage your binder language, but that is a discussion for another day. My preference is to identify a single signature for the service program and add new exports to the bottom of the list. This means I can use the RTVBNDSRC command with option MBROPT(*ADD) to add new exports to the list. It works as follows:
A Couple of Handy User Actions By now you have probably guessed that this structure does not allow for all the default options on the relevant commands. For example, say I created a new module (REGF05A) and wanted to add the exports to the binder language source member. The command would be:
Code 4:
RTVBNDSRC MODULE(REGF05A) SRCFILE(REGFUNC)
SRCMBR(REGFUNC)MBROPT(*ADD)
I needed to change the name of the source file, the name of the source member and, of course, change the MBROPT to *ADD (the default of *REPLACE would be a disaster). Or when I go to create a service program, I would need to use the command:
Code 5:
CRTSRVPGM SRVPGM(SIDMAINTV2/REGFUNC) MODULE(REGF*)
SRCFILE(REGFUNC)
TEXT('And I have to remember the text I use')
Again, the name of the source file for the export member needs to be changed and I have to remember what the text is for the service program. So to make life a little easier for myself, I set up a few User Actions in RSE. You can create User Actions by right-clicking on an item in a filter (e.g., a member name) and, from the context menu, select User Actions, Work with User Actions. These are the equivalent of User Defined Options in PDM. Figure 2 shows the Work with Actions pane with three member actions defined. The first of these is an option to update a service program that has the same name as the source file (SRVPGM(&F)), with the module that has the same name as the member (MODULE(&N)). The abbreviations used for files, objects, libraries, etc., are the same as those used in PDM.
At the bottom of the window I have indicated that this option should only be available for RPG resource types. In other words, this option will only be visible when I right-click on an RPG source member and select User Actions, as shown in Figure 3.
Figure 4 shows the definition of an option to perform a RTVBNDSRC operation on the module that has the same name as the member (MODULE(&N)) and add to a member in the same source file (SRCFILE(&F)), the member should have the same name as the source file (SRCMBR(&F)) and exports should be added (MBROPT(*ADD)). As with the previous example, this action should only be available for RPG resource types.
Figure 5 shows the definition of an option to perform a CRTSRVPGM of a service program with the same name as the member (SRVPGM(&N)). The export source file and source member should both have the same name as the source file (SRCFILE(&N) SRCMBR(&N)), and the text should have the same text as the selected member (TEXT(&X)). Since there isn’t a way of specifying the generic name we want to use (unless we create an option for each service program), we identify that the modules used to create the service program begin with an X (MODULE(X*)), and I tick the option to Prompt First, which means the command will be prompted when I select the user action and I can change the MODULE parameter. Note that the service program will be created in the current library so ensure that the current library for the connection is the program/service program library. (In this instance it should be SIDMAINTV2.)
One of the problems with the Create a Service Program User Action is that I only want it to be available to members with a member type of BND. The BND member type is not available under any of the Defined Types, so I created a new type (ILE) by clicking on the Edit(H) button and defining a member type as shown in Figure 6.
Back To the Standard Programs Now that you have an idea how the Service Programs are maintained, there are a couple of points to note about the standard programs.
Code 6--Contents of the Include Members STDHSPEC and BASEINFO:
STDHSPEC
H Debug DatEdit(*MDY/) Option(*SrcStmt:*NoDebugIO)
H DftActGrp(*No) ActGrp('AGCGI') BndDir('SIDBNDDIR':'QC2LE')
BASEINFO
/include utility,pUtility
/include fileProcs,protoFile
/include common,commproto
/include genstat,pStatGen
/include regFunc,pRegFunc
//--------------------------------------------------------
// Include CGI Prototypes, if required
/If Defined(CGIPGM)
/include CGIDEV2/QRPGLESRC,PrototypeB
/include CGIDEV2/QRPGLESRC,Usec
/EndIf
//--------------------------------------------------------
// Include HSSF Prototypes, if required
/If Defined(HSSF)
/include SIDSrc,HSSF_H
/EndIf
There You Have It I wouldn’t expect anyone to adopt this as their standard but, hopefully, it might give you some ideas as to how you might tune your current development environment–especially with user actions. And that, at the moment, is my development environment. But by the time the next RPG & DB2 Summit comes around you might get completely different answers to:
Paul Tuohy is CEO of ComCon, an iSeries consulting company, and is one of the co-founders of System i Developer, which hosts the RPG & DB2 Summit conferences. He is an award-winning speaker who also speaks regularly at COMMON conferences, and is the author of “Re-engineering RPG Legacy Applications,” “The Programmers Guide to iSeries Navigator,” and the self-study course called “iSeries Navigator for Programmers.” Send your questions or comments for Paul to Ted Holt via the IT Jungle Contact page.
|