Title: MOVE11: Using Classes and Procedures in OpenEdge 10
1MOVE-11 Using Classes and Procedures in
OpenEdge 10
- Exploiting the benefits of Object-orientation
Bruce S Gruenbaum
Principal Software Engineer, OpenEdge Architect
Development
2Purpose of this Talk
What are the take-aways?
- Object-orientation is not a difficult transition
to make - Useful addition to the language
- Can improve the quality of your product
- Can speed products time-to-market
- Not an all or nothing decision
- You can and should use procedural where applicable
3Under Development
- This talk includes information about potential
future products and/or product enhancements. - What I am going to say reflects our current
thinking, but the information contained herein is
preliminary and subject to change. Any future
products we ultimately deliver may be materially
different from what is described here.
4Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
5Why should I care about Object-orientation?
Object-orientations big benefits
- Object-orientation is a highly structured way to
build applications - Simpler modeling tool integration, e.g. roundtrip
engineering - Code benefits
- Less bugs
- More reuse
- Business benefits
- Time to market
- Better maintainability
6Why should I care about Object-orientation?
How do we get the benefits?
- Strong Typing
- Less runtime processing
- Improved quality through finding errors at
compile-time - Class hierarchy known at compile-time
- Re-use
- Abstraction means code re-use
- Classes can be deployed for re-use
- Improved quality and higher productivity
7Strong Typing
What is a Type?
- A contract with the compiler
- A data type with data and behavior that conforms
to a certain structure or contract - Examples of a Type
- Customer with name, address, contact details and
a method for purchasing from suppliers - All instances of a type are guaranteed to adhere
to that contract - Type does not define how the contract was
implemented - Just that it exists
8Strong Typing
- Implemented as
- Classes and Interfaces in OO
- Persistent procedures and handles in procedural
- Does not require runtime type-checking
9Strong Typing
Procedure
Class
CLASS Customer METHOD PUBLIC VOID
PurchaseStuff (INPUT b AS CHARACTER)
/ buy the stuff / END METHOD. END CLASS.
/ Customer.p / PROCEDURE PurchaseStuff DEF
INPUT PARAMETER b AS CHARACTER NO-UNDO. /
buy the stuff / END.
PurchaseStuff exists in this Persistent Procedure
but not all Persistent Procedures
Class Customer always has PurchaseStuff (contract)
10Runtime Type Checking
Do you have procedural code like this?
Is this a persistent procedure?
PROCEDURE InternalA DEFINE INPUT PARAMETER pHn
AS HANDLE. IF pHnTYPE PROCEDURE AND
CAN-DO(phnINTERNAL-ENTRIES,PurchaseStuff)
AND pHnGET-SIGNATURE(InternalB) /
check sig/ THEN DO RUN PurchaseStuff IN
pHn. END. ELSE / handle the error / END.
Does it have an internal procedure called
PurchaseStuff?
Does the signature match?
Now we can run it
11Compile-Time Type Checking
In OO it looks like this
METHOD PUBLIC VOID InternalA (INPUT a AS
Customer) aPurchaseStuff(). END.
- Less Code
- No runtime checking
- No runtime errors
Automatically checked all 3 conditions at compile
time. Just run the thing!
Strong Typing is your friend
12The Cost of Object-orientation
- Requires more forethought than procedural
- Type hierarchies can be hard to change
- Refactoring and modeling can help
- Requires a base class library to get started
- Base classes can take a while to build
- Different mindset from procedural
- Easier, if you have worked with super procedures
before
13Object-orientation versus Procedural
OO
Procedural
- Types are created at run-time
- Type definition is loosely bound
- Inheritance is determined at run-time
- Provides flexibility for generic code
- Types are known at compile time
- Type definition is contractual
- Inheritance is set at design-time
- Prevents run-time type errors
14What do I use? Procedural or OO?
You dont have to choose one or the other!!!
- Use the one that is most appropriate for the task
- Use procedural for generic late-bound programming
- Use OO for inheritance
- You can mix them
- Procedural can instantiate classes
- Classes can call procedures
- Procedural is not going away
- You dont have to replace any procedural code
with OO
15Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
16Mapping Classes to Procedures
- Classes are the basis of OO development
- Define data and behavior of types
- Similar to persistent procedures
- Can be instantiated multiple times
- Have similar structure
- Instantiated using NEW
- Instead of RUNPERSISTENT SET
17Mapping Procedures to Classes
Classes
Procedure
- Procedure Files (.p)
- Main block code
- Internal Procedures
- Functions
- ON CLOSE
- Super procedures
- Class Files (.cls)
- Constructor
- Void Methods
- Method
- Destructor
- Inheritance
18Mapping Procedure Structure to Class
Persistent Procedure
Class
CLASS Customer CONSTRUCTOR PUBLIC
Customer() END CONSTRUCTOR. METHOD PUBLIC
VOID PurchaseStuff() END METHOD.
DESTRUCTOR PUBLIC Customer() END
DESTRUCTOR. END CLASS.
/ Customer.p / / Main block code
/ PROCEDURE PurchaseStuff END
PROCEDURE. ON CLOSE OF THIS-PROCEDURE DO
DELETE PROCEDURE THIS-PROCEDURE. END.
19Comparing Procedure Invocation To Class
Procedure
Class
DEF VAR v AS Customer. v NEW
Customer(). vPurchaseStuff(). DELETE OBJECT
v.
DEF VAR h AS HANDLE. RUN Customer.p
PERSISTENT SET h. RUN PurchaseStuff IN
h. APPLY CLOSE TO h.
20So what are the differences?
- Public data members
- Variables exposed outside the class
- Package name
- Provides path information
- Access modifiers
- PRIVATE, PROTECTED and PUBLIC
- Classes are Types
- Procedures are always just HANDLES
21Additional Class Functionality
Calling code
Class
DEF VAR f AS AR.Data.Customer. f NEW
Customer(). fName Lift Ski. fPurchaseStuff
(). fAddToInventory().
CLASS Customer DEF PUBLIC VAR Name AS
CHARACTER. CONSTRUCTOR PUBLIC foo() END
CONSTRUCTOR. METHOD PUBLIC VOID
PurchaseStuff() END METHOD. METHOD
PRIVATE VOID AddToInventory() END
METHOD. END CLASS.
1
3
Class is at AR/Data/Customer.cls
2
2
4
3
4
5
5
Doesnt compile. Method is private.
22Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
23Procedural OO Interoperability
- You can mix them!
- Procedural can call OO
- OO can call procedural
- You should mix them
- Existing code is procedural
- Some new code may be OO
24Using a Class in a Procedure
Define a global (to the procedure) variable as a
class
DEF VAR c AS Customer. c NEW Customer(). RUN
a. PROCEDURE a DEF VAR c1 AS Customer. c1
NEW Customer(). c1PurchaseStuff().
cPurchaseStuff(). RUN b ( INPUT c1 ). END
PROCEDURE. PROCEDURE b DEF INPUT PARAMETER p
AS Customer. pPurchaseStuff(). END PROCEDURE.
Instantiate an instance
Define a local variable as a class
Instantiate a second instance
Call method on local variable
Call method on global variable
Call procedure passing class as parameter
Define parameter as a class
Call a method on the parameter
25Using a Procedure in a Class
Run a procedure persistently
CLASS Customer DEF VAR hProc AS HANDLE
NO-UNDO. CONSTRUCTOR PUBLIC Customer() RUN
Customer.p PERSISTENT SET hProc. END
CONSTRUCTOR. METHOD PUBLIC PurchaseStuff()
RUN PurchaseStuff IN hProc. RUN
getCustomer.p. y DYNAMIC-FUNCTION(getTotal
IN hProc). END METHOD. DESTRUCTOR PUBLIC
Customer() APPLY CLOSE TO hProc. END
DESTRUCTOR. END CLASS.
Run an internal procedure
Run an external procedure
Use function dynamically
Processing procedure events
26Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
27Using Inheritance
What is it?
- Generalized members reused by a subtype
28Using Inheritance
What is it?
RE-USE
- Generalized members reused by a subtype
29Using Inheritance
What is it?
Inheritance
- Generalized members reused by a subtype
30Procedural Inheritance
- Inheritance is available today
- Through super procedures
- Hierarchy established by ADD-SUPER-PROC
- Use TARGET-PROCEDURE to call code in initiator
- Only bound at runtime
- Requires runtime resolution
- No strong typing
- Easy to make mistakes that are hard to find
- Super can be recompiled alone
31Procedural Inheritance Example
Procedure
Super Procedure
DEF VAR h AS HANDLE. RUN super.p PERSISTENT
SET h. THIS-PROCEDURE ADD-SUPER-PROCEDURE
(h,SEARCH-TARGET). PROCEDURE a / do some
stuff / RUN SUPER. END PROCEDURE. PROCEDURE
b / do some stuff / RUN SUPER. END.
PROCEDURE a RUN b IN TARGET-PROCEDURE. END. PR
OCEDURE b / do some stuff / END.
1
4
2
6
3
5
32Object Oriented Inheritance
- Bound at compile time
- Strongly typed - errors caught at compile-time
- Subtype can be used where super type is expected
- Call automatically invokes in most derived class
- Hierarchy established by INHERITS statement
- Changing super means a recompiles
33Object Oriented Inheritance Example
Super Class
Subclass
CLASS Parent METHOD PUBLIC VOID a() b().
/ calls the one in Child / END
METHOD. METHOD PUBLIC VOID b() / do some
stuff / END METHOD. END CLASS.
CLASS Child INHERITS Parent METHOD PUBLIC
OVERRIDE VOID a() / do some stuff /
SUPERa(). END METHOD. METHOD PUBLIC
OVERRIDE VOID b() / do some stuff /
SUPERb(). END METHOD. END CLASS.
2
3
6
1
4
5
34Important Things to Note
- PROTECTED may only be accessed by class and
subtypes - OVERRIDE is required
- Tells the compiler youre doing this deliberately
- Subtypes method is always called
- May specify FINAL on Class or Method
- Overriding is not allowed
- Multiple inheritance is not allowed
35Interfaces
- Define a contract with the compiler
- Guarantees a class will have certain members
- No implementation in the interface
- Classes implement interfaces
- May be more than one
- Must provide implementation for all members
- Compiler validates that implementation has
occurred
36Why do I need Interfaces?
Avoid all that extra checking!!!
To avoid this
PROCEDURE InternalA DEFINE INPUT PARAMETER pHn
AS HANDLE. IF pHnTYPE PROCEDURE AND
CAN-DO(phnINTERNAL-ENTRIES,PurchaseStuff)
AND pHnGET-SIGNATURE(InternalB) /
check sig/ THEN DO RUN PurchaseStuff IN
pHn. END. ELSE / handle the error / END.
37Why do I need Interfaces?
Classes
Interface
CLASS Child INHERITS Parent IMPLEMENTS
IFamily METHOD PUBLIC VOID c() / do
some stuff / END METHOD. END CLASS.
INTERFACE IFamily METHOD PUBLIC VOID c(). END
CLASS.
1
1
Caller
2
DEF VAR chld AS Child. DEF VAR csn AS
Cousin. chld NEW Child(). csn NEW
Cousin(). RUN proc(chld). RUN proc(csn). PROCEDUR
E proc DEF INP PAR x AS IFamily. xc(). END.
CLASS Cousin INHERITS Uncle IMPLEMENTS
IFamily METHOD PUBLIC VOID c() / do
some stuff / END METHOD. END CLASS.
1
2
38Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
39Working with OO Restrictions
OO imposes necessary restrictions
- Type checking
- How to write generic code?
- No global variables
- How to set session wide variables?
- Cannot RETURN ERROR from methods
- How to trap errors?
40Type Checking
How to write generic code?
- Use interfaces as far as possible
- All classes inherit from Progress.Lang.Object
- ToString()
- GetClass()
- NEXT-SIBLING
- PREV-SIBLING
- Equals()
- Clone()
- Use CAST function to set as subtype
41Progress.Lang.Object example
Class
Caller
CLASS Child INHERITS Parent IMPLEMENTS
IFamily METHOD PUBLIC OVERRIDE VOID
a() / do some stuff / SUPERa(). END
METHOD. METHOD PUBLIC VOID c() / do
some stuff / END METHOD. END CLASS.
DEF VAR chld AS Child. chld NEW Child(). RUN
proc(chld). PROCEDURE proc DEF INPUT
PARAMETER x AS Progress.Lang.Object. DEF
VAR z AS Child. DEF VAR y AS Parent.
DISPLAY xToString(). y CAST(x, Parent).
ya(). z CAST(x,IFamily). zc(). END.
42Global Variables
How to set session-wide variables?
- Other OO languages have STATIC
- We will too in the future
- Need access to existing global variables
- Cannot be accessed in classes
- OO-Procedural interop helps
43Global Variables Example Procedural Side
Globals.p
DEF NEW GLOBAL SHARED VAR ghAppServer AS
HANDLE. FUNCTION getAppServer RETURNS HANDLE
() RETURN ghAppServer. END FUNCTION. FUNCTION
setAppServerHandle RETURNS LOGICAL (INPUT ph AS
HANDLE) ghAppServer ph. END FUNCTION.
44Global Variables Example OO Side
CLASS foo DEF VAR hGlobal AS HANDLE NO-UNDO.
CONSTRUCTOR PUBLIC foo() RUN Globals.p
PERSISTENT SET hGlobal. END CONSTRUCTOR.
METHOD PUBLIC WorkWithGlobal() DEF VAR
hAppServer AS HANDLE NO-UNDO.
DYNAMIC-FUNCTION(setAppServer IN hGlobal,
hAppServer). hAppServer DYNAMIC-FUNCTION(ge
tAppServer in hGlobal). END METHOD.
DESTRUCTOR PUBLIC foo() DELETE PROCEDURE
hGlobal. END DESTRUCTOR. END CLASS.
Starts the global variables procedure
persistently!
45Error Handling
How to trap errors?
- Other OO languages have try catch
- We will have something like it too
- Need to write code that traps errors today
- Transactions fail, records are not found
- OO-Procedural interop helps again
46Error Handling 3 step program
- Create an Error class
- Make methods return or output this class
- If it is not used, set the value to ?
- Trap errors using procedural code
47Error Handling Define the Error class
CLASS MyError DEF VAR cError AS CHARACTER
NO-UNDO. CONSTRUCTOR PUBLIC MyError(INPUT
pcError AS CHARACTER) cError pcError.
END CONSTRUCTOR. METHOD PUBLIC CHARACTER
GetError() RETURN cError. END METHOD. END
CLASS.
Lets go to the next slide to see how we use this
class.
48Error Handling Catching the Error
CLASS Customer METHOD PUBLIC MyError
FindRecord() DEF VAR errStat AS MyError.
errStat ?. FIND FIRST Customer NO-ERROR.
IF NOT AVAILABLE(Customer) errStat NEW
MyError(Customer not found). RETURN
errStat. END METHOD. METHOD PUBLIC LOGICAL
CallFindCode(OUTPUT pcError AS MyError)
RUN find.p NO-ERROR. IF ERROR-STATUSERROR
THEN pcError NEW MyError(RETURN-VALUE).
END METHOD. END CLASS.
49Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
50Demo Putting it all together
- Demonstrate all the stuff we have learned
51Debugging Memory Management
Debug ? Diagnostics ? Monitor Dynamic Objects
If this area is empty youve done well. If there
are still objects at the end you need to add a
few DELETE OBJECT statements
52Agenda
What were going to cover
- Why should I care about Object-orientation?
- Explaining OO from a procedural perspective
- Procedural OO Interoperability
- Using Inheritance
- Working with OO restrictions
- Putting it all together
- Where to from here?
53Where to from here?
- OO is not difficult and has some great benefits
- Most of you have been doing similar code for
YEARS - Procedural is alive and well
- Dont change everything
- Use what you need
- Lots more OO to come
54For More Information, go to
- OpenEdge 10.1A documentation
- OpenEdge Getting Started Object-Oriented
Programming
55Great books on Object-orientation
- The Object Oriented Thought Process
- SAMS publishing
- Design Patterns
- Gamma, et al, Addison Wesley
- Patterns of Enterprise Application Architecture
- Martin Fowler, Addison Wesley
56Relevant Exchange Sessions
- DEV-1 Introduction to Object-Oriented Language
Concepts and Programming in the OpenEdge ABL
with Evan Bleicher - DEV-6 Advanced Object-Oriented Programming in
the ABL with Evan Bleicher and Shelley Chase - INNOV-14 A Look Inside the OpenEdge UI Research
Lab with Shelley Chase and Bruce Gruenbaum
57Questions?
58Thank you foryour time
59(No Transcript)