× 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.


  • Subject: Re: Programming philosophy Was:RPG IV program - comment
  • From: "Scott Klement" <infosys@xxxxxxxxxxxx>
  • Date: 28 Sep 1999 12:05:25 -0500

Buck Calabro <mcalabro@commsoft.net> wrote:
>
> I see what you're saying.  As usual, I said half of what I should
>  have, and
> twice as much as I needed to.  When I say "intent" I mean to say tha
>  the
> programmer intended to solve some business problem.  The more the co
> reveals the chosen solution to that business problem, the clearer th
> "intent."  Historically, the closer we get to the hardware/operating
>  system,
> the more obscured the solution becomes.  Imaging how long it would
>  take to
> decipher the assembler instructions used by a simple PC application
>  like
> EDLIN.  This is what makes abstraction such a powerful tool for
>  writing
> programs and solving business problems.  I'm not concerned with whic
> register I need to store values in, or how many bytes I can read int
>  the
> I/O buffer before it overflows, or what columns does a field occupy
>  a
> record.

Believe me, Buck, you're preaching to the choir!  All of my programs
are modular in design.   I usually take the approach that I'm
"creating my own extensions to the language" for each application
that I write.

My general approach to the design of the program is to figure out
what lower-level reusable routines I would need to make a program
that's very easy to read, yet clearly illustrates what my program
does and how it does it.

I then, based on this design create a high-level program, which
in simple cases consists of only a mainline -- or in more complicated
cases may consist of more.

And finally, I create procedures to handle the lower level stuff.

This approach allows me to write programs very quickly, because it
forces me to think of everything that I'm going to need to do at
the outset, and create an outline (in code) for how my program will
function at the outside, while still allowing me a great deal of
reusability in my code.

>
> >Our shop uses naming standards that make it immediately
> >obvious which fields come from which files.  These standards
> >make it impossible for fields in one file to have the same
> >name as fields in another file.
>
> Great!  I only wish that more shops had similar standards (any
>  standards?!)

Our shops standards save me HOURS every day.  Literally takes hours
off of the workload that I would otherwise have, and saves my company
having to pay more people.  It does this by making it immediately
obvious what a variable or field is, where it comes from and where it
is likely to go.  This saves me having to search up and down through
all of the code figuring out what something is... and makes it very
easy to see why code does what it does.

I am fortunate to be in a position where I can enforce that standards
are followed by the other people around me.   This hasn't always been
the case however -- when I have to deal with older code that didn't
follow the standards, I really realize how useful those standards are.

> >With the EXCEPT approach, you now have to go down to
> >the Output specs to see whats affected, so for us, it would
> >make things more difficult to follow.
>
> This is an interesting, fairly common complaint.  I believe that thi
>  has kept modular coding from "catching on" in the midrange market.
>  Rather than /COPY or another program/module ("I can't see the code
>  unless I open another window..."), we have oodles of inline code
>  that's been copied from other programs.  This doesn't encourage
>  very modular code.

Agreed.  If a procedure is written properly, you shouldn't need to
know how it works.  It works and has been well tested, and you're
just employing it to get a task done.

The same goes for using UPDATE instead of EXCEPT!  Take the following
example: (sorry about the indicator, but I'm V3R2)

C     kyCUSTMAS     CHAIN     CUSTMAS                            30
C                   if        *IN30 = *Off
C                   eval      cuOrdDate = wkOrdDate
c                   eval      cuOnOrder = cuOnOrder + wkOrdQty
c                   update    CUSTMASF
c                   endif

Assuming that you're familiar with our system...  each field that
starts with "cu" is part of the Customer Master file.   Each field
that starts with "wk" is a local "work" variable.

Its very clear here that I'm updating the date ordered and the
quantity on order.   If instead it said:

C     kyCUSTMAS     CHAIN     CUSTMAS                            30
C                   if        *IN30 = *Off
C                   eval      cuOrdDate = wkOrdDate
c                   eval      cuOnOrder = cuOnOrder + wkOrdQty
c                   except    UpdCustmas
c                   endif

...  a few hundred lines of code ...

OCUSTMAS   E            UpdCustmas
O                       cuOrdDate
O                       cuOnOrder

Now I had to go down and check the output specs to make sure that
both of the fields were being updated...  Granted, this isnt a big
deal, but its SOMETHING...

What if one of the fields in the output specs has been (gasp)
indicator conditioned?  This is (IMHO) a bad practice, but unless
I wrote the program, I don't know that its not being done!

Another fun thing you can do with output specs, is indicator condition
the whole record, and have multiple record updates/writes/prints that
happen depending on the state of indicators in the program... talk
about masking your intent!

> The alternative, to use many, small and easy to understand modules i
> understood to be _the_ way to go in the rest of the programming worl
>   It
> is impractical to have an open window for each function your program
>  is to
> perform; this is why naming conventions are so important:
> GetBasePrice(ProductCode:Price) is so much easier to follow than
> GETPRC(ITM:AMT)  I'm still talking about "intent" here.  If the
>  programmer
> who wrote GetBasePrice did it properly, the name reflects exactly wh
>  the
> function does - Get the base price for the item.  Nothing more.  Not
>  verify
> quantities or warehouse availability.  It does one thing and one thi
>  well.
> When the maintenance programmer (me) comes along, I should not _have
>  to
> look inside GetBasePrice to figure out what it does.  The intent
>  should be
> clear.

With UPDATE, its very clear to me whats happening right there in
my C specs.   With EXCEPT, theres still other logic that COULD be
happening...

As you stated, a well written sub procedure will tell you exactly
what its going to do, and you can rely on it to do that.   However,
an EXCEPT doesn't follow those rules.  You don't know what its going
to do unless you look at the code -- EXCEPT could mean many different
things!   Update, however, is very clear as to what its doing.

Again, however, this is based on the fact that I can tell exactly
what fields belong to what file just from seeing the names in the C
specs, this is very different in other situations...


> Back to Excpt and O specs:  Yes, you have to look at the O specs to
>  see what
> is happening, and yes, this distracts the programmer from the intent
>  of the
> code, but I might suggest the following construct:
>
> C* Update if customer has tolls this month
> C                   If        STATUS = ACTIVE_G
> C                   CallP
>  UpdCusYTDFrmTol(Customer:TOLYTD:TOLAMT:TOLDAT)
> C                   EndIf
>
> ORMaster   E            UpdMasTol
> O                       TOLYTD
> O                       TOLAMT
> O                       TOLDAT
>
> PUpdCusYTDFrmTol  b
> DUpdCusYTDFrmTol  pi
> D Cus_I                         10    const
> D YTD_I                         15  0 const
> D Amt_I                         15  0 const
> D Dat_I                          8S 0 const
>
> C     CusKey        Klist
> C                   Kfld                    Cus_I
>
>  * Lock record
>  * ASSUMPTION - THIS RECORD ALREADY EXISTS!!
> C     CusKey        Chain     RMaster
> C                   If        %found
> C                   Add       YTD_I         TOLYTD
> C                   Add       Amt_I         TOLAMT
> C                   Z-Add     Dat_I         TOLDAT
> C                   Except    UpdMasTol
> C                   EndIf
>
> PUpdCusYTDFrmTol  e
>
> With something like this, I should not have to go poke around in the
>  guts of UpdCusYTDFrmTol to figure out what's getting updated. I
>  can look at the parameters and clearly see what goes in, right at
>  the eval.  If something is broken, the business problem (Keep track
>  of the last toll date and cumulative amount for quick inquiry
>  performance) is implemented in one function, and should be easily
>  repaired.
>
>  I hope *my* intent finally came through! :-)
>
> Buck Calabro

I agree with you here, because you put your code in a procedure,
and didn't use global variables, this makes it quite clear what you're
doing, and normally I wouldn't need to look at this procedure and
see what its doing.

However, if we're talking about using EXCEPT vs. UPDATE, (rather
than the merits of modular programming)  I still say that UPDATE
is a better choice for much of the same reasons that modular
code is a better choice.   (Same reasons that I listed above...)

A few notes about this particular procedure, however:

1) If the record doesn't exist, you've got a problem.   Your
     procedure should have some sort of a success/failure return
     value...

2) Although you've taken care to ensure that you only update a few
     fields, the only fields that you COULD have updated are the
     ones between the "if %found" and the "except", since you just
     re-loaded the record in your procedure!

3) Since fields from a file are global, your CHAIN could've
     (potentially) changed values in another area of your program.
     Unfortunately, this is one of the limitations of RPG programs,
     you can't declare fields from a file to be local to a
     sub-procedure.  I personally don't like my sub-procedures to
     change anything but the parameters being passed to them, and
     the return value.

     Of course, the easy workaround for this would be to put all
     of the routines that access a file into a seperate module,
     and only pass field values to your main program via parameters,
     but...  we'll leave that discussion for another time :)

Scott
+---
| This is the RPG/400 Mailing List!
| To submit a new message, send your mail to RPG400-L@midrange.com.
| To subscribe to this list send email to RPG400-L-SUB@midrange.com.
| To unsubscribe from this list send email to RPG400-L-UNSUB@midrange.com.
| Questions should be directed to the list owner/operator: david@midrange.com
+---


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.