+ Reply to Thread
Results 1 to 6 of 6

Thread: RPG Object?

  1. #1
    Guest.Visitor Guest

    Default RPG Object?

    Just thought I'd share a technique I've been using over the past few months - maybe someone can use it or suggest improvements. I use data structures as a means of passing data between procedures. An example might be a customer master maintenance transaction, where an interactive maintenance program is passed the data structure, does it's interacting with a user, passes the data structure back and forth between editing procedures, and eventually passes the data structure along to a procedure that updates the data-base. One of the draw-backs with this approach is that if you add fields to this data structure, everything that uses it must be re-compiled and moved live simultaneously. . The technique to avoid this goes like this: Create a service program where the data structure is defined internally. Write a pair of get/set procedures for every field within the data structure (this is pretty time-consuming), and define these procedures as exportable. This way, if you add new fields, you just add them to the service program's internal data structure, add a couple more get/set procedures, then move the service program live. Everything still works fine, and you can then start making your changes to only those programs that actually need the new fields (ie they'll call the new get/set procedures). I guess this is a crude form of object, but it's been fairly useful in some situations. One example is where we have a whole series a display formats that collect all manner of data for a sale, but users want the ability to go back and forth between these formats, making changes as they go, but not comitting any change to file until enter is pressed on the last screen. Each format is presented by its own display program, so the service program 'object' is used to carry around the work done by all the display programs.

  2. #2

    Default RPG Object?

    On Tuesday, March 23, 1999, 01:23 AM, J V Thompson wrote: I use data structures as a means of passing data between procedures. An example might be a customer master maintenance transaction, where an interactive maintenance program is passed the data structure, does it's interacting with a user, passes the data structure back and forth between editing procedures, and eventually passes the data structure along to a procedure that updates the data-base. One of the draw-backs with this approach is that if you add fields to this data structure, everything that uses it must be re-compiled and moved live simultaneously.
    A GOOD thing for a database (I love level checking, yet another reason I am somewhat biased against SQL), but a bad thing for APIs. Especially backwardly compatible APIs, which are required in a distributed environment.
    [/i] The technique to avoid this goes like this: Create a service program where the data structure is defined internally. Write a pair of get/set procedures for every field within the data structure (this is pretty time-consuming), and define these procedures as exportable. This way, if you add new fields, you just add them to the service program's internal data structure, add a couple more get/set procedures, then move the service program live. Everything still works fine, and you can then start making your changes to only those programs that actually need the new fields (ie they'll call the new get/set procedures). [/i]
    Ta da! Instant backwards compatibility. There are some other tricks you can play here as well. Two have to do with defaults. The first is the ability to have default values for the fields not "set" by the user. Whenever a new instance of the "RPG Object" is created, you can default the new fields to a suitable value. But let's take that one step further: you can default ALL the fields, and not only that, you can have routines (methods grin) that SET the default values. Call them once at the beginning of a session to set session defaults like User ID and company and such, and those fields need not be set during regular processing!
    [/i] I guess this is a crude form of object, but it's been fairly useful in some situations. One example is where we have a whole series a display formats that collect all manner of data for a sale, but users want the ability to go back and forth between these formats, making changes as they go, but not comitting any change to file until enter is pressed on the last screen. Each format is presented by its own display program, so the service program 'object' is used to carry around the work done by all the display programs. [/i]
    Bravo, John! Bravissimo! You've just made a major step towards encapsulating your APIs. The nice thing is that this allows you to do some cool things with messages later on. But we'll leave that for another day grin. href="//www.zappie.net/java"> src="//www.zappie.net/java/_derived/index.htm_cmp_zero110_vbtn_p.gif" width="140" height="60" border="0" alt="Zappie's Java Home" align="middle">

  3. #3
    Guest.Visitor Guest

    Default RPG Object?

    On Tuesday, March 23, 1999, 01:23 AM, J V Thompson wrote: Just thought I'd share a technique I've been using over the past few months - maybe someone can use it or suggest improvements. I use data structures as a means of passing data between procedures. An example might be a customer master maintenance transaction, where an interactive maintenance program is passed the data structure, does it's interacting with a user, passes the data structure back and forth between editing procedures, and eventually passes the data structure along to a procedure that updates the data-base. One of the draw-backs with this approach is that if you add fields to this data structure, everything that uses it must be re-compiled and moved live simultaneously. . The technique to avoid this goes like this: Create a service program where the data structure is defined internally. Write a pair of get/set procedures for every field within the data structure (this is pretty time-consuming), and define these procedures as exportable. This way, if you add new fields, you just add them to the service program's internal data structure, add a couple more get/set procedures, then move the service program live. Everything still works fine, and you can then start making your changes to only those programs that actually need the new fields (ie they'll call the new get/set procedures). I guess this is a crude form of object, but it's been fairly useful in some situations. One example is where we have a whole series a display formats that collect all manner of data for a sale, but users want the ability to go back and forth between these formats, making changes as they go, but not comitting any change to file until enter is pressed on the last screen. Each format is presented by its own display program, so the service program 'object' is used to carry around the work done by all the display programs. From your comments, you are following the object model of modular programming. We use that method and we have many ILE modules that perform gets, puts and validates. We place most of these modules into service programs. However our transactions are actual programs not service programs. There is so much emphasis on the object model today, that we forget that other models also exist. In addition to the object model, we make use of the 3 tier model. Object programming does not replace the 3 tier model. The two work together. For transactions, the object model really does not work as well as the 3 tier model. The 3 tier programming model says that every business transaction you have should have a defined format. You should have a "Business Rules" program that edits and processes the transaction. The "Presentation programs" call the business rule programs. As a result you will have a single business rules program processes a transaction from any data source. At our site, the web server, the 5250 display screens or batch transfer all use the same business rule programs. Taking the abstract concepts of 3 tier or object programming and creating an actual working solution takes some work. At our shop the presentation programs call a tranaction control program that then calls the actual program that processes the transaction. The transaction control program uses a transaction class id to lookup the name of the business rules program. The business rule programs are actual programs, not modules. A single program validates, adds, cancels or modifies a particular business transaction. The business rule programs and the presentation programs call the gets, puts and validate functions. These are modules and usually operate on individual fields. Like ValidateDealerNo or ValidatePartNo. These are usually in service programs. To call the transaction control program, we pass 3 control block parameters and 1 or 2 data parameters. The first data parameter is the header record of the transaction. If the transaction has detail records, the second data parameter contains a table of the detail items. The length of the records, the number of items in the table and the size of the table is contained in the control block information. The data table for detail items is a dynamic table that can be reallocated by the business rules program or the presentation program. This requires them to belong to the same activation group. To make this all work, the presentation program is compiled to a named activation group. Usually the name of the program. The transaction control program and business rules program are compiled as activation group *caller. Sometimes when I add a field to the transaction, I have the business rules program check the length of the record received to make sure it contains the new field. This way I can modify the business rules program and not have to modify all of the presentation programs at the same time. We have a few transactions that have 12 presentation programs, but most have 3 or less. Changing a transaction format and recompiling them all is not that large a task. Even object oriented languages like Java need to have some method to pass transactions between modules. Java beans are one method of doing so. The presentation program gets the data and calls the Java bean. How do you handle errors? This is a major design issue for modular code. If a error occurs, we want the presentation program to display a message and highlight the field that has an error. A message like, invalid part number on a 100 line order is unacceptable. There must be a way for the presentation program to tie the errors returned from the business rules program to particular line item and field. To do this you need some table of return codes that are identified by the line and field that the code belongs to. When you considered everything, transaction processing requires its own calling convention. It needs its own unique set of paramters that do not fit into the object calling convention. JHicks@SUZ.com

  4. #4
    Guest.Visitor Guest

    Default RPG Object?

    On Tuesday, March 23, 1999, 02:10 PM, Jim Hicks wrote: How do you handle errors? This is a major design issue for modular code. If a error occurs, we want the presentation program to display a message and highlight the field that has an error. A message like, invalid part number on a 100 line order is unacceptable. There must be a way for the presentation program to tie the errors returned from the business rules program to particular line item and field. To do this you need some table of return codes that are identified by the line and field that the code belongs to.
    We've spent quite a bit of time on this one, and haven't yet come up with the ideal solution. For the moment, the post-enter logic in the presentation program looks like this (read X_ fields to be the actual display fields, and the set/get/edt procs reside in the 'object' service program):
     callp setField1(X_FLD1) callp setField2(X_FLD2) eval MsgID=edtField1(Parms) if MsgID<>*BLANKS callp dspError('X_FLD1':MsgID:Parms) endif eval MsgID=edtField2(Parms) if MsgID<>*BLANKS callp dspError('X_FLD2':MsgID:Parms) endif eval X_FLD1_D=getField1Desc eval X_FLD2_D=getField2Desc 

  5. #5
    Guest.Visitor Guest

    Default RPG Object?

    On Tuesday, March 23, 1999, 02:10 PM, Jim Hicks wrote: .......... When you considered everything, transaction processing requires its own calling convention. It needs its own unique set of paramters that do not fit into the object calling convention. Jim Could you expand on this ? David

  6. #6
    Guest.Visitor Guest

    Default RPG Object?

    On Tuesday, March 23, 1999, 02:10 PM, Jim Hicks wrote: ...To call the transaction control program, we pass 3 control block parameters and 1 or 2 data parameters. The first data parameter is the header record of the transaction. If the transaction has detail records, the second data parameter contains a table of the detail items. The length of the records, the number of items in the table and the size of the table is contained in the control block information. The data table for detail items is a dynamic table that can be reallocated by the business rules program or the presentation program. This requires them to belong to the same activation group. To make this all work, the presentation program is compiled to a named activation group. Usually the name of the program. The transaction control program and business rules program are compiled as activation group *caller. Sometimes when I add a field to the transaction, I have the business rules program check the length of the record received to make sure it contains the new field. This way I can modify the business rules program and not have to modify all of the presentation programs at the same time. We have a few transactions that have 12 presentation programs, but most have 3 or less. Changing a transaction format and recompiling them all is not that large a task. Even object oriented languages like Java need to have some method to pass transactions between modules. Java beans are one method of doing so. The presentation program gets the data and calls the Java bean. How do you handle errors? This is a major design issue for modular code. If a error occurs, we want the presentation program to display a message and highlight the field that has an error. A message like, invalid part number on a 100 line order is unacceptable. There must be a way for the presentation program to tie the errors returned from the business rules program to particular line item and field. To do this you need some table of return codes that are identified by the line and field that the code belongs to. When you considered everything, transaction processing requires its own calling convention. It needs its own unique set of paramters that do not fit into the object calling convention. JHicks@SUZ.com Jim, I think the main part that is missing from RPGIV is the ability to pass parameterized types. If you could do this you could create a very object like interface between your procedures. To get around this I ended up not using RPG's parameter passing. Instead, each field, file, format, and application is described in files. This information is used to store data. Each field is given a unique ID. Each application supplies a context. When a record is read (screen, or database) the unique ID and context are used to retrieve or set field values. This ends up being much simpler from an application standpoint. For example, to validate a fields value prior to a file update, the application calls the edits associated with file/field passing the application context. No parameters. The edit can then retrieve any file/field or screen/field because it knows the context and what is required to edit the value. If the application has neglected to retrieve a value that is required for the edit an application error will be signaled. If the field value is invalid, the associated field error flag is set. If all of the edits and database exist for an application there is nothing to compile. At this point, high volume transaction files are an exception. For performance reasons the database is statically linked to the field edits. This is not required during the prototyping/testing phase. I have not yet completed a command interpreter so applications that do not follow a pre-defined flow also require code. One thing that makes sending messages back to an application is the use of a single queue for messages. I hit on this idea while trying to come up with a method to send messages by level in ILE programs. The PEP procedures were causing problems. I ended up creating a data area in qtemp that contains the current program message queue. For interactive jobs the default is the initial program for the job. For vendor supplied applications it is set prior to external calls, or by the database trigger program. This way even programs like DBU get field edit error messages on the screen. Batch jobs do not get the data area, and default to caller. A side benefit was the ability to pass messages to programs that were not yet active. David Morris

+ Reply to Thread

Similar Threads

  1. IFS object
    By Guest.Visitor in forum CL
    Replies: 2
    Last Post: 12-08-2006, 06:01 AM
  2. Object Changes
    By David Abramowitz in forum General
    Replies: 11
    Last Post: 01-24-2003, 09:36 AM
  3. getting DDS from Object.
    By praveen53@yahoo.com in forum General
    Replies: 2
    Last Post: 10-07-2002, 07:01 AM
  4. Object locks
    By wtyost@foodlion.com in forum RPG
    Replies: 0
    Last Post: 05-02-2002, 05:05 AM
  5. Object Authority.
    By Guest.Visitor in forum Analysis
    Replies: 6
    Last Post: 09-21-2000, 09:19 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts