× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Nathan/All,

Observations, IMHO and my experience embedded in your reply.



Paul,

Your file maintenance utility has inspired me.  I'm considering writing a
generic component in RPG, not for maintaining, but for browsing files.  I
can envision exporting an api such as the following:

 fileReference = browseClass_Open(Library:File:Member)

 browseClass_SetFileReference(fileReference)
 browseClass_ListFromTop(recordCount)
 browseClass_ListNext(recordCount)
 browseClass_ListPrevious(recordCount)
 browseClass_ListFromBottom(recordCount)
 browseClass_ListFromKey(key:recordCount)

 ...

 browseClass_Other()
**************************************************
Nathan,  good stuff here.  Your "browse file" component or object that your
propose building is the most common user requirement that we see in
application development with our clients.

How many applications have required these generic requirements?:

a)  Show me x fields from file y in library z
b)  Show me 10 at a time
c)  For column c use "Last Name" as the column header and ...
d)  More advanced:  Allow me to search based on field x and allow me to sort
on any field
e)  Plus several additional generic requirements

It may be a little light weight without the associated verbal description
but I've documented our approach to this "#1 Most common programming task"
in the following PowerPoint:
http://www.planetjavainc.com/pres/AdvancedJavaDesignPatternsInWeb_files/fram
e.htm  (specifically in the "select and display section")

Again, it is our view/goal to automate this #1 redundant requirement into a
generic component that can be used regardless the specific
library/file/member you are "browsing".   If we can do that, we have
shortened the time required to develop applications significantly.

A few features from your api that may need to consider are:

a)  Fields to display?  Often, files have 100's of fields and requirements
often state show me fields (a, c, d , p, and r).  Perhaps adding a parm to
your "browseClass_Open(Library:file:member:field1, field 2, field 3, etc)?
This allows the api user to state dynamically, what fields they want to
display in their result.

b)  Associated with the generic browse requirement, is the need to allow the
user to specify "runtime dynamic selection" to the browse.  For example, if
browsing an INVOICE file, the user often wants to be able to specify "Find
Invoice By Number" and then they supply the invoice # at runtime.  So your
api may have "browseClass_setSelectionFields("INVOICE_NUM")"  Obviously your
design must support multiple selection fields with the array of conditions
support such as "INVOICE_DATE > ? and CUSTOMER# = ? or /and ...."  This is
kinda like a generic QUERY/400 component with dynamic prompt.

c)  The other huge need is to support specific requirements based on each
field being displayed.  For example, if your browse file facility is showing
a salary field you would want to apply current formatting or if browsing a
employee department field, you may need to supply a F4 (prompt) to allow
selection of a specific department.  Other "field" specific characteristics
include:  column header, possible values (f4), formatting, authority to
view, update, links or associations to other data (set lower limit and chain
to an associated file).  This is kinda like what DDS allows you to specify
but you really need more intelligence with your fields to be generic yet
powerful to a wide range of applications.

d)  When returning your record set from your api, you also need to know if
there are more records so you can generate the "next page" feature, etc.

e) actually several more generic parms to support here....
***************   </end generic "browse file" component >




**********  From Nathan***************
I don't think I'd want to bite off generic add, change, and delete
procedures, because such actions are generally subject to complex business
rules that would need to be overridden and adapted to individual
circumstance anyway.
*********  end Nathan *********


<Business Rule Design for Complex individual circumstances>

   This is an excellent scenario to further explore OO and it's capabilities
in terms of productive application development.   Actually we an accommodate
these complex business rules rather easily and quickly.

   This is nearly impossible (IMHO) to design completely generically
although we can generically do most all of it.  However, most applications
and businesses have unique and "unpredictable" rules that apply when a)
Adding a new record  b) updating a record c) deleting a record, etc.....

For example: assume a typical set of business rules in a HR application:

a)  Employees that are "MANAGERS" cannot be updated by this application,
they are handled by process "Z" so DON"T ALLOW MANAGERS to be edited.
b)  Also, validate that any "NON-MANAGER" employees cannot be assigned a
salary > 125000 "   Our company's compensation policy restricts salaries to
this limit.  and blah blah blah...


So, the requirement in this case is to allow "employee data" to be updated
but restrict the updates to these conditions...

The code to generically update a record can be fairly easily written and
inherited for EVERY file in EVERY database and we simply allow specific
complex business rules to be specified for this particular database record
for "ROW" by overriding the generic insert, update, and delete methods.

For example:  I enhanced the Java400 demonstration application at:
http://www.planetjavainc.com/wow60/runApp?id=298

to support these features:  a)  In the "Employees" operation only return 10
records at a time    b)  Don't allow editing (see edit icon to the left of
each data row) if the employee is a "Manager" or his name is "Nathan"   c)
When updating a Row, disallow updates if the employee is not a manager and
an attempt is made to set the salary > 125000

This is a small example of complex business requirement.

The net is this:  The general behavior of insert, update, delete is common
for any relational database record;  a framework should allow this default
behavior but you MUST allow specific "non predictable" business rules to be
enforced.  This requirement was enabled basically with 2 "IF " statements
and 2 minutes of development time as shown below;  Everything else needed to
update, insert, delete is inherited:

Java class to enforce business rules:

package PlanetJ.example;

import PlanetJ.DataEngine.exception.*;
import planetj.DataEngine.*;

public class Employee extends PlanetJ.database.Row {

/**
 * Check to see if this Row may be edited.  By default, all Rows may be
 * edited.  Subclasses may override to implement a different behavior.
 *
 * @pram ec  context in which application is executing.
 *
 * @return  true if Row may be edited; false otherwise.
 */
public boolean isEditable(ExecutingContext ec) {

        try {

                // If the employee is a Manager or Nathan (just an example)
don't allow the Row to be edited
                if (getValueAsString("JOB").equalsIgnoreCase("MANAGER") ||
getValueAsString("FIRSTNME").startsWith("NATHAN")) {
                        return false;
                }
                else {
                        return true;
                }
        }
        catch (Throwable t) {
                t.printStackTrace();
                return false;
        }
}
/**
* Validate if the operation can be performed on this Row.
* <p>
* @param: int pOpteration Constants stored in Row  ie. Row.INSERT
* @param: java.security.Principal pUser
* @exception DataEngineException if a this any field is invalid.
*/
public void validateRowOperation(int pOperation, java.security.Principal
pUser) throws DataEngineException {


                switch (pOperation) {
                        case (INSERT) :
                                // Whatever you want to validate on insert
                        case (UPDATE) :

                                { // If the employee is a Manager they can't
have a salary > 125000
                                        if ( (!
getValueAsString("JOB").equalsIgnoreCase("MANAGER")) &&
getValueAsDouble("SALARY") > 125000) {

                                                throw new
DataEngineException("Hey they ain't worth that much! Lower that salary!");
                                        }

                                }

                        case (DELETE) :
                                // Whatever you want to validate on delete
                        case (COPY) :
                                // Whatever you want to validate on copy
                }
        }


}

********************************


This design approach is shown here:
http://www.planetjavainc.com/html/demo.html

You can edit the application here:
http://www.planetjavainc.com/wow60/WOWBuilder
Use userid:  "support@xxxxxxxxxxx"  and   password "support" to logon then
go to step 3 setup operations.   NOTE:  this is on on of our development
systems; it might go up and down a few times a day for software updates....

NET:  We are after productivity.   We now have a much more complex business
application with specific rules enforced but have only spent about 15
minutes total on the application.

</end>



















There are more similarities between ILE and OO languages than most people
realize.  For object instantiation in RPG:

 Eval myInstance = myClass_New(parameters)

 Callp myClass_doSomething(myInstance: parameters)

Where myInstance would be a pointer to a data structure containing instance
properties, which would be referenced from myClass procedure calls.

For inheritance in RPG, create a new module, either importing and wrapping
the procedures in a base module, or create a new module containing just
procedure overrides, then bind to both modules.

For polymorphism in RPG, define data exports in modules, supplementing
procedure interfaces, which alter the behavior of procedures based on data
content.

It's true that most RPG programmers wouldn't consider following OO design
patterns, unless they first immersed themselves in OO languages for a period
of years.  But I returned to RPG for both performance as well as
productivity reasons.

Nathan.

As an Amazon Associate we earn from qualifying purchases.

This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.