| Pete Dashwood 2006-03-08, 7:55 am |
|
"James J. Gavan" <jgavandeletethis@shaw.ca> wrote in message
news:AqvPf.121958$H%4.62432@pd7tw2no...
> Frank Swarbrick wrote:
>
> Do about 12 Page Downs to get to my comments, finishing with a question on
> Components for PECD :-
>
>
> Not sure that I understood that last bit - are you thinking of how you
> store variables related solely to the method - if so, then that's the
> method's Local-Storage Section.
>
> Method-id. "doSomething".
> *>----------------------
> Local-Storage section.
> 01 ls-TempKounter pic s9(6)v9(05).
> Procedure Division.
> compute ls-TempKounter = GlobalKounter1 * 2
> compute GlobalKounter2 = ls-TempKounter * 6
> End Method "doSomething".
> *>---------------------------
>
> The two GlobalKounters are in Working-Storage.
>
> Above using 'ignore red tape' could be written in M/F as :-
>
> Method-id. "doSomething".
> 01 ls-TempKounter pic s9(6)v9(05).
> compute ls-TempKounter = GlobalKounter * 2
> compute GlobalKounter2 = ls-TempKounter * 6
> End Method "doSomething".
>
>
> Your revision certainly has appeal to me. Just using the Micro Focus
> feature 'ignore red tape' I left out lines where the compiler can
> currently automatically recognize what's coming up next. Your revised
> source was roughly 69 lines, mine below some 87 lines.
>
> There's no way this will compile in Net Express V 3.1 - Most of it would
> compile in V 4.0 onwards, although it would hiccup at your copyfile
> entries. Not having the V 4 compiler it *might* accept some of your
> references to Java. Here's your example modified to leave out the red tape
> junk. (I'll leave the comment lines in, just so I don't cheat )
>
> *>---------------------------------------------------------------
> Class-id. Account inherits Base.
>
> Repository.
> Class Base is "java.lang.Object"
> Class Account is "Account".
> *
> Factory.
> Working-storage section.
> 01 NumberOfAccounts pic 9(6) value zero.
> *
> * createAccount method to create a new Account
> * instance, then invoke the OBJECT paragraph's init
> * method on the instance to initialize its instance data:
> Method-id. "createAccount".
> Linkage section.
> 01 inAccountNumber pic S9(6) binary.
> 01 outAccount object reference Account.
> * Facilitate access to JNI services:
> Copy JNI.
> Procedure Division using by value inAccountNumber
> returning outAccount.
> * Establish addressability to JNI environment structure:
> Set address of JNIEnv to JNIEnvPtr
> Set address of JNINativeInterface to JNIEnv
> Invoke Account New returning outAccount
> Invoke outAccount "init" using by value inAccountNumber
> Add 1 to NumberOfAccounts.
> End method "createAccount".
> *
> End Factory.
> *
> Object.
> Working-storage section.
> 01 AccountNumber pic 9(6).
> 01 AccountBalance pic S9(9) value zero.
> *
> * init method to initialize the account:
> Method-id. "init".
> Linkage section.
> 01 inAccountNumber pic S9(9) binary.
> Procedure Division using by value inAccountNumber.
> Move inAccountNumber to AccountNumber.
> End method "init".
> *
> * getBalance method to return the account balance:
> Method-id. "getBalance".
> Linkage section.
> 01 outBalance pic S9(9) binary.
> Procedure Division returning outBalance.
> Move AccountBalance to outBalance.
> End method "getBalance".
> *
> * credit method to deposit to the account:
> Method-id. "credit".
> Linkage section.
> 01 inCredit pic S9(9) binary.
> Procedure Division using by value inCredit.
> Add inCredit to AccountBalance.
> End method "credit".
> *
> * debit method to withdraw from the account:
> Method-id. "debit".
> Linkage section.
> 01 inDebit pic S9(9) binary.
> Procedure Division using by value inDebit.
> Subtract inDebit from AccountBalance.
> End method "debit".
> *
> * print method to display formatted account number and balance:
> Method-id. "print".
> Data division.
> Local-storage section.
> 01 PrintableAccountNumber pic ZZZZZZ999999.
> 01 PrintableAccountBalance pic $$$$,$$$,$$9CR.
> Procedure Division.
> Move AccountNumber to PrintableAccountNumber
> Move AccountBalance to PrintableAccountBalance
> Display " Account: " PrintableAccountNumber
> Display " Balance: " PrintableAccountBalance.
> End method "print".
> *
> End Object.
> *
> End class Account.
> ---------------------------------------------------------------
>
> Initially liked your idea of shuffling the Linkage syntax to the
> Method-name line - but it really is shuffling. Look at the following,
> where having used a class AppHouse(keeping) to create a Cheese Treeview,
> it returns values to AppDriver. (Having got back to AppDriver I can
> destroy/finalize AppHouse which is no longer required :-
>
> *>-------------------------------------------------------------
> Method-id. "begin".
> *>------------------------------------------------------------
> Local-storage section. *> <---- could have left this out
> copy "\copylib\sqlResult.cpy" replacing==(tag)== by ==01 ws==.
> 01 n pic x(4) comp-5.
> Linkage section.
> 01 lnk-Caller object reference.
> 01 lnk-MakeAstring object reference.
> 01 lnk-Parent object reference.
> 01 lnk-Resource object reference.
>
> 01 lnk-Objects.
> 05 lnk-ChoiceDialog object reference.
> 05 lnk-DBI occurs MaxLevels object reference.
> 05 lnk-TvControl object reference.
> 05 lnk-TvDialog object reference.
> 05 lnk-TvPopup object reference.
>
> Procedure Division using lnk-Caller
> lnk-MakeAstring
> lnk-Parent
> lnk-Resource
> returning lnk-Objects.
>
> *> This class performs initial 'housekeepng' and then
> *> passes control back to AppDrive.cbl :-
> ETC...........
>
> Now it's not often that you want to move a bunch of stuff like above.
> Possibly 90% plus of your methods have only ONE parameter (an object, pic
> x or a pic 9). But the above does make it clear what is happening.
>
> STATIC DATA :
>
> Seeing as I think both you, Oliver and Pete (with reference to his
> Components), have mentioned it. Went looking in the N/E V 4.0 OO on-line
> manual - no reference to static, so didn't help much.
>
> Now take the example you have shown us. My contention is that the FACTORY
> method could be in the OBJECT, like so :-
>
> The calling program/class which contains in its Repository :-
>
> Class Account is "Account". then invokes :-
>
> invoke Account "new" returning os-AccountObj
> invoke os-AccountObj "createAcccount"
> using thisAccountNumber(binary) returning thisAccount(object)
>
> and "createAccount" and the invoked "init" are part and parcel of one
> method in the OBJECT Section. Then of course you are incrementing the
> NumberOfAccounts.
>
> Real world - we may perhaps statistically want to know the total number of
> new Accounts we have opened to-day. Now I'll put my wife behind a cash
> register at the Bay (Hudson's Bay Company). Marketing - "Get as many
> customers as you can to open a Bay credit card account and we'll give you
> a voucher for $5". Want to keep tabs on how many accounts Eileen has
> managed to 'sell' ? You need Number of Accounts but in the the INSTANCE
> that she is using :-
>
> 'z' instances x numberOfAccounts = TotalAccounts at this store
>
> which is a pass-back from the individual instances to the Control Program
> when the cash register is shut down. Same I'm sure would apply with
> tellers in banks with any promotional schemes you have.
>
> Similarly I can't see your Java code would hiccup if it was part of an
> INSTANCE (OBJECT) method as opposed to a FACTORY method. Java is after all
> in the example being used to control object creation/destruction.
>
> The nearest I came in relevance to FACTORY from my OO Manual was :-
>
> ----------------------------------------------------------------------
> Data Inheritance
>
> A factory object inherits all the factory data of its superclass, and an
> instance object inherits all the instance data of its superclass. The
> inherited data of a subclass includes any data that the superclass itself
> inherited from a class higher up the hierarchy. The inherited object data
> is initialized when an object is created. The inherited factory data is
> allocated independently from the factory data of the inherited class or
> classes when the factory of the subclass is created. A subclass can only
> access inherited data through the methods it inherited from the same
> class. For example, if the class Manager inherits from the class Employee,
> and Employee defines the data item:
>
> employeeNumber PIC 999
>
> The Manager class cannot store a value in its inherited employeeNumber
> data item by using a statement such as:
>
> move 100 to employeeNumber
>
> Instead it must use a method declared in the Employee class, for example:
>
> invoke self "setEmployeeNumber" using 100
>
> The object reference SELF is a reserved name which always refers to the
> object in which it occurs (see the section ....
> -------------------------------------------------------------------------
> The Factory Object Source Element
>
> The factory object source element defines the data and methods for the
> factory object. It is nested within the class source element, immediately
> following the class source element's Data Division (if there is one). It
> looks like this:
>
> factory.
> working-storage section.
> * factory data .
> ...
> * factory methods
> end factory.
>
> The factory object data is defined in the Working-Storage Section. ***The
> factory object data can only be accessed from the factory methods*** - my
> Asterisks.
> ----------------------------------------------------------------------------
> Factory Methods
>
> Each factory method is a nested source element. The code below shows an
> outline for a "new" method for Stopwatch.
>
> method-id. "new".
> ...
> linkage section.
> 01 lnkWatch object reference.
>
> procedure division returning lnkWatch.
> * code to create and initialize a Stopwatch object.
> exit method.
> end method "new".
>
> As with the class source element itself, you can declare different types
> of data in the Data Division of the method. The DATA DIVISION header
> itself is optional. Data declared here is only accessible to the code in
> this method. The Data Division can contain any of the following sections:
>
> * Local-Storage Section
>
> Data items that are local to the current invocation of a method. The
> method uses local storage for all its temporary working data. This has the
> advantage of supporting recursion.
> * Linkage Section
>
> Variables passed as parameters to and from the method.
>
> The Procedure Division contains the code for the method. You terminate
> processing of the method with an EXIT METHOD statement. This returns
> processing to the program which invoked the method.
>
> To see the "new" method, use the Editor to locate the "new" method, below
> tag S015. This method uses a Linkage Section to return data from the
> method.
> The Instance Object Source Element
>
> The instance object source element defines the data and methods for
> instances of the class. It is nested within the class source element. It
> looks like this:
>
> object.
> working-storage section.
> * instance data for the object.
> ...
> * Instance methods
> end object.
>
> The only Data Division section that has any meaning in an object source
> element is the Working-Storage Section. You can create other data
> sections, but the run-time behavior if you try to access the data in these
> sections is undefined.
>
> Any data you declare in the Working-Storage Section is accessible to all
> the instance methods, and may be inherited by instances of subclasses of
> the class.
>
> There is no Procedure Division in an object source element, only methods.
> To write an initialization method for instances, write a method called
> "initialize", and then invoke it from the "new" method for the class after
> you have created an instance.
>
> To see the object source element and data declarations paragraph for
> Stopwatch, use the Editor to locate the OBJECT header. The OBJECT header
> and Working-Storage Sections are located below tags S030 and S035.
> Instance Methods
>
> Instance methods are nested inside the object source element. Writing an
> instance method is exactly like writing a factory method, with the only
> difference being the scope of data which the instance method can access.
>
> The instance method can access data:
>
> * Declared in the Data Division of the instance method source element
>
> * Declared in the Working-Storage Section of the object source element
> ----------------------------------------------------------------------------
>
> Now just tracking to N/E sample on 'Bank Accounts' - what else; that's
> what they all use. They do use FACTORY similar to above to create a new
> account. But is that just doing it by rote because that's the perceived
> way that everybody does it, regardless of language. Or are FACTORY methods
> irrelevant and they could be contained in the OBJECT ?
>
> You Java boys convey how static gets used in Java, to counter what I've
> written above.
>
> Pete, above is not complete references. However where it says, "***The
> factory object data can only be accessed from the factory methods*** ". If
> you are passing parameters/properties for Components to FACTORY how do
> they get referenced from Instance/Object methods ?
>
By invoking GET and SET factory methods from an instance.
(You need a reference to the Factory first...Unless you are late binding or
accessing the Class as a COM/ActiveX component (which is what I mostly
do...) and that's beyond the scope here.)
Here's how you would establish an early bound reference to a factory
property in Fujitsu NetCOBOL, from within an instance of the Class:
01 factoryObj USAGE OBJECT REFERENCE FACTORY OF MyClass [ONLY].
....
invoke factoryObj "GET-factory-property"
RETURNING some-factory-property
end-invoke
....
invoke factoryObj "SET-factory-property"
USING some-instance-property
end-invoke
There is way too much here to comment on, so I won't. :-) I do believe some
of the subtlety of using factory in OO COBOL has been entirely missed in the
discussions here, particulary it's use to produce new instances, and to hold
state variables for the Class, but it really doesn't matter...:-)
I already posted on this in response to you and Oliver.
I would stress I don't do this myself (early binding... I almost
exclusively use late bound ActiveX/COM) and I certainly don't pass
parameters to methods (factory or otherwise) unless I absolutely HAVE to,
and it makes sense to do so. The stability of the interface is more
important (to me) than the obvious solution. I don't want to have to change
parameter lists and recompile stuff, because I don't intend to maintain the
source. I can use factory or instance properties with GET and SET methods to
achieve the same result, and my interface never changes.
Obviously, this approach requires extensive design and modelling to ensure
that all the necessary (and in some cases, unnecessary [right now])
properties are included. Despite the perceived wisdom here in CLC, it is not
impossible to identify all attributes for a given process, but you probably
won't do it using the waterfall. (SDLC tends to identify required outputs,
known inputs, and design to those.) OO/component based design looks at
processes as methods of objects (entities, if you like). Properties are
established in support of the processes, and not because they are required
on a signed off report or screen layout. (In the RAD environment these
requirements can change frequently and there are no sign-offs apart from
handover and acceptance testing...) Events and how they will be handled are
also part of the design process. Data and process modelling, data flow
analysis, and Use Case simulations are all part of the OO design approach I
use. It works for me, and I don't maintain code. 'Do it once; do it right'
:-)
Pete.
|