ARCH-7: A Class-Based Implementation of the OpenEdge ® Reference Architecture John Sadd Fellow and...
-
Upload
vernon-blankenship -
Category
Documents
-
view
227 -
download
1
Transcript of ARCH-7: A Class-Based Implementation of the OpenEdge ® Reference Architecture John Sadd Fellow and...
ARCH-7: A Class-Based Implementation of the OpenEdge® Reference Architecture
John SaddFellow and OpenEdge Evangelist
Applied Technology
© 2007 Progress Software Corporation2 ARCH-7: A Class-based Implementation of the OERA
Goals for the session
Show practical implications of the OpenEdge Reference Architecture
Show how ABL support for classes is useful Discuss some interesting issues and choices
© 2007 Progress Software Corporation3 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation4 ARCH-7: A Class-based Implementation of the OERA
OpenEdge Reference ArchitectureFor Service Oriented Business Applications
Design for longevity, flexibility, and competitive advantage
Accommodates evolving business requirements
Anticipates trends in technology
Provides agile and flexible architecture
PresentationPresentation
Business ComponentsBusiness Components
Data AccessData Access
Data SourcesData Sources
Co
mm
on
Infrastru
cture
Co
mm
on
Infrastru
cture
Enterprise ServicesEnterprise Services
© 2007 Progress Software Corporation5 ARCH-7: A Class-based Implementation of the OERA
Basic Architecture Principles
Avoid duplicated code!• “ABL is a great language – we want you to write
less of it.”
• Do every job once and only once.
• Outlaw Copy-Paste-Edit!
• Factor! Factor! Factor!
Don’t hardwire things that are liable to change!• That’s what the OERA layers are there for…
© 2007 Progress Software Corporation6 ARCH-7: A Class-based Implementation of the OERA
Implementing the OpenEdge Reference Architecture on PSDN
© 2007 Progress Software Corporation7 ARCH-7: A Class-based Implementation of the OERA
For example: Business Entities using Procedures
Server BE procs
dsOrder.i
{etOrder.i}
{etOrderLine.i}
{etItem.i}
DEFINE DATASET…
Data Access Object
SUPER
SUPER
Template procedures Include files Super procedures RUN VALUE (…)
Business Entity
beOrder.p
beEntity.i
RUN daOrder.p
PROC fetchWhere:
…
Super Procedure
beSupport.p
beOrderValidate.p
(optional)
eOrderLineModifyPreTrans:
© 2007 Progress Software Corporation8 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation9 ARCH-7: A Class-based Implementation of the OERA
Basic principles of using classes in ABL
Strong typing• Compiler knows exactly what everything is
• Compiler cross-checks classes
• Much more robust error checking at compile time
Inheritance of common behavior• Definitional, not done at runtime
• Compiler checking of validity
• Always invoke the most-derived version
© 2007 Progress Software Corporation10 ARCH-7: A Class-based Implementation of the OERA
Overview of server-side classes
© 2007 Progress Software Corporation11 ARCH-7: A Class-based Implementation of the OERA
Top-level class componentbase.cls
CLASS base.componentbase IMPLEMENTS interfaces.iComponent:/* Base class for all objects. Locates the service manager, which it expects some startup routine to have created.*/ DEFINE PROTECTED PROPERTY servicemgr AS service.servicemgr NO-UNDO GET. PRIVATE SET. CONSTRUCTOR PROTECTED componentbase(): DEFINE VARIABLE sessionObject AS progress.lang.object. sessionObject = SESSION:FIRST-OBJECT. DO WHILE VALID-OBJECT(sessionObject) AND sessionObject:GetClass():TypeName <> 'service.servicemgr': sessionObject = sessionObject:NEXT-SIBLING. END. IF NOT VALID-OBJECT(sessionObject) THEN FatalError( "Session management service not found!"). ELSE servicemgr = CAST (sessionObject, service.servicemgr). END CONSTRUCTOR. METHOD PUBLIC VOID FatalError (pcMessage AS CHAR): MESSAGE "Fatal error!" SKIP pcMessage VIEW-AS ALERT-BOX ERROR. END.
© 2007 Progress Software Corporation12 ARCH-7: A Class-based Implementation of the OERA
The CLASS statement
The CLASS statement identifies the class by name and by package to the compiler
If it INHERITS another class this is named If it IMPLEMENTS an interface this is named
CLASS base.componentbase IMPLEMENTS interfaces.iComponent:
INTERFACE interfaces.icomponent: METHOD PUBLIC VOID initializeComponent(). METHOD PUBLIC VOID destroyComponent().END INTERFACE.
© 2007 Progress Software Corporation13 ARCH-7: A Class-based Implementation of the OERA
Data members and properties
Data members in a class can be PUBLIC, PROTECTED, or PRIVATE
The data type can be a class type For added control you can define data as
properties• GET phrase controls read access and behavior• SET phrase controls write access and behavior
DEFINE PROTECTED PROPERTY servicemgr AS service.servicemgr NO-UNDO GET. PRIVATE SET.
© 2007 Progress Software Corporation14 ARCH-7: A Class-based Implementation of the OERA
Constructors and destructors in classes
The CONSTRUCTOR represents the “main block” code
It can have parameters but no return type It can be inherited and overridden
CONSTRUCTOR PROTECTED componentbase():
…
END CONSTRUCTOR
The DESTRUCTOR represents the code to execute when the object is deleted
It has no parameters and no return type It is reliably invoked unless the whole session
ends unexpectedly
© 2007 Progress Software Corporation15 ARCH-7: A Class-based Implementation of the OERA
The object hierarchy
CONSTRUCTOR code locates the service manager
DEFINE VARIABLE sessionObject AS progress.lang.object.
sessionObject = SESSION:FIRST-OBJECT. DO WHILE VALID-OBJECT(sessionObject) AND sessionObject:GetClass():TypeName <> 'service.servicemgr': sessionObject = sessionObject:NEXT-SIBLING. END. IF NOT VALID-OBJECT(sessionObject) THEN FatalError( "Session management service not found!"). ELSE servicemgr = CAST (sessionObject, service.servicemgr).
progress.lang.object
service.servicemgr
sessionObject
servicemgr
CAST
DEFINE PROTECTED PROPERTY servicemgr AS service.servicemgr NO-UNDO GET. PRIVATE SET.
© 2007 Progress Software Corporation16 ARCH-7: A Class-based Implementation of the OERA
Methods in classes
Methods take the place of internal procedures and functions
They define parameters and a return type like functions do
VOID means there’s no return type Like data members, they are PUBLIC,
PROTECTED, or PRIVATE
METHOD PUBLIC VOID FatalError (pcMessage AS CHAR): MESSAGE "Fatal error!" SKIP pcMessage VIEW-AS ALERT-BOX ERROR. END.
© 2007 Progress Software Corporation17 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation18 ARCH-7: A Class-based Implementation of the OERA
Business Entities and Data Access Objects
© 2007 Progress Software Corporation19 ARCH-7: A Class-based Implementation of the OERA
Business Component classes
CLASS base.businesscomponent INHERITS base.componentbase:
CLASS base.businessentity INHERITS base.businesscomponent IMPLEMENTS interfaces.ibusinessentity: DEFINE PROTECTED VARIABLE dataAccess AS base.dataaccessobject.
METHOD fetchData(): dataAccess:loadData().
CLASS samples.beCustomer INHERITS base.businessentity: {samples/dsCustomer.i} CONSTRUCTOR PUBLIC beCustomer (): dataAccess = CAST (servicemgr:startService (‘samples.daCustomer',"da"), samples.daCustomer). END CONSTRUCTOR. METHOD PUBLIC OVERRIDE VOID validateData(): SUPER:validateData(). validateCustomer(INPUT-OUTPUT DATASET-HANDLE hdsDataset BY-REFERENCE). END METHOD. METHOD PRIVATE VOID validateCustomer(INPUT-OUTPUT DATASET dsCustomer):…
© 2007 Progress Software Corporation20 ARCH-7: A Class-based Implementation of the OERA
Data Access classes
CLASS base.dataaccess INHERITS base.componentbase:
CLASS base.dataaccessobject INHERITS base.dataaccess IMPLEMENTS interfaces.idataaccess:…METHOD PUBLIC VOID loadData(): hdsDataset:EMPTY-DATASET(). setFillMode('MERGE':U). attachDatasource(). fillDataset(). detachDatasource(). END METHOD.
CLASS samples.daCustomer INHERITS base.dataaccessobject: {samples/dsCustomer.i &REFERENCE-ONLY=REFERENCE-ONLY} METHOD PUBLIC OVERRIDE VOID attachDatasource(): bufferDatasource('ttCustomer', 'Customer', 'CustNum', '', 'FOR EACH Customer'). END METHOD.
© 2007 Progress Software Corporation21 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation22 ARCH-7: A Class-based Implementation of the OERA
OpenEdge Reference Architecture:How do you invoke a Business Component?
PresentationPresentation
Business ComponentsBusiness Components
Data AccessData Access
Data SourcesData Sources
Co
mm
on
Infrastru
cture
Co
mm
on
Infrastru
cture
Enterprise ServicesEnterprise ServicesClient session
AppServer™ session
© 2007 Progress Software Corporation23 ARCH-7: A Class-based Implementation of the OERA
Principles for making calls to the AppServer
You can run a procedure on an AppServer You can run an internal procedure, but only by
binding the AppServer session first• Binding the AppServer is not a good idea• This also requires multiple calls to complete a
single request You want the AppServer to be stateless You cannot instantiate a class on the AppServer You don’t want clients directly calling Business
Component classes anyway! So: Define a procedure on the server to handle a
specific request for a specific Business Component type
© 2007 Progress Software Corporation24 ARCH-7: A Class-based Implementation of the OERA
The Service Adapter and Service Interface
PresentationPresentation
Business ComponentsBusiness Components
Data AccessData Access
Data SourcesData Sources
Co
mm
on
Infrastru
cture
Co
mm
on
Infrastru
cture
Enterprise ServicesEnterprise ServicesClient session
AppServer session
Service AdapterService Adapter
Service InterfaceService Interface
© 2007 Progress Software Corporation26 ARCH-7: A Class-based Implementation of the OERA
The role of the Service Adapter
You don’t want client objects knowing the details about Business Components• Where they’re located
• Exactly what their APIs are
• How to route a request to them
The Service Adapter provides a key layer of indirection and discovery
© 2007 Progress Software Corporation27 ARCH-7: A Class-based Implementation of the OERA
The role of the Service Interface
Defines a point of entry for each accessible method in each Business Component
Static parameters for those methods so they are self-describing
Common services invoked consistently and automatically• Authentication, security, context…
So you want client Service Adapters calling Service Interface procedures!
© 2007 Progress Software Corporation28 ARCH-7: A Class-based Implementation of the OERA
The Service Adapter class on the client
CLASS pres.serviceadapter INHERITS base.componentbase: CONSTRUCTOR PUBLIC serviceadapter(): hAppServer = IF VALID-HANDLE(SESSION:FIRST-SERVER) THEN SESSION:FIRST-SERVER ELSE SESSION:HANDLE. END CONSTRUCTOR.
METHOD PUBLIC VOID fetchData (OUTPUT DATASET-HANDLE dsDataset): RUN VALUE(getSIPath() + "_fetchdata.p") ON hAppServer (OUTPUT DATASET-HANDLE dsDataset). END METHOD.
METHOD PROTECTED CHARACTER getSIPath (): RETURN ?. END METHOD.END CLASS.
CLASS samples.pres.saCustomer INHERITS pres.serviceadapter: METHOD PROTECTED OVERRIDE CHARACTER getSIPath(): RETURN “samples/api/beCustomer". END METHOD.END CLASS.
© 2007 Progress Software Corporation29 ARCH-7: A Class-based Implementation of the OERA
The Service Interface procedure on the server
/* becustomer_fetchdata.p */ &SCOPED-DEFINE PACKAGE-NAME samples &SCOPED-DEFINE COMPONENT-NAME customer &SCOPED-DEFINE METHOD-NAME fetchData &SCOPED-DEFINE PARAM-LIST {templates/fetchdata_params.i} &SCOPED-DEFINE PREFIX-NAME be &SCOPED-DEFINE DATASET-MODE OUTPUT {templates/apicode.i}
servicemgr:sessionContextService:setContextId(pcContextId).authenticationService = servicemgr:authenticationService.authenticationService:loadPrincipal().
{&PREFIX-NAME}{&COMPONENT-NAME} = CAST (servicemgr:startService ('{&PACKAGE-NAME}.{&PREFIX-NAME}{&COMPONENT-NAME}', "{&PREFIX-NAME}"), {&PACKAGE-NAME}.{&PREFIX-NAME}{&COMPONENT-NAME}). {&PREFIX-NAME}{&COMPONENT-NAME}:{&METHOD-NAME}({&PARAM-LIST}).
© 2007 Progress Software Corporation30 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation31 ARCH-7: A Class-based Implementation of the OERA
Repeatable elements in an application
Service Adapter
class
Service Interface
procedureBusiness Entity
class
Data Access Object
class
Data Source Object
class
© 2007 Progress Software Corporation32 ARCH-7: A Class-based Implementation of the OERA
Business Entity class template
/*---------------------------------------------------------------------File : be<entity-name>.clsPurpose : Generated from the template for Business Entity classes Description : Sample Business Entity for <entity-name> Edited : April 2007 ---------------------------------------------------------------------*/ CLASS <package-name>.be<entity-name> INHERITS base.businessentity: {<package-name>/ds<entity-name>.i &REFERENCE-ONLY=REFERENCE-ONLY} CONSTRUCTOR PUBLIC be<entity-name>(): dataAccess = CAST (servicemgr:startService (‘<package-name>.da<entity-name>', "da"), <package-name>.da<entity-name> ). END CONSTRUCTOR.…END CLASS.
© 2007 Progress Software Corporation33 ARCH-7: A Class-based Implementation of the OERA
List of preprocessors and other values
PACKAGE-NAME ENTITY-NAME (or COMPONENT-NAME) PREFIX-NAME (e.g., ‘be’) For Data-Sources:
• Temp-table name• Database table list• (Optional) database key field list• Field mapping between physical and logical• Base DB query (‘FOR EACH <table-name>’)
© 2007 Progress Software Corporation34 ARCH-7: A Class-based Implementation of the OERA
Business Entity with the blanks filled in
/*---------------------------------------------------------------------File : beCustOrder.clsPurpose : Generated from the template for Business Entity classes Description : Sample Business Entity for CustOrderEdited : 04/04/07 ---------------------------------------------------------------------*/ CLASS Sports2000.CustOrder.beCustOrder INHERITS base.businessentity: {Sports2000.CustOrder/dsCustOrder.i &REFERENCE-ONLY=REFERENCE-ONLY} CONSTRUCTOR PUBLIC beCustOrder(): dataAccess = CAST (servicemgr:startService ('Sports2000.CustOrder.daCustOrder',"da"), Sports2000.CustOrder.daCustOrder). END CONSTRUCTOR.…END CLASS.
© 2007 Progress Software Corporation35 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation36 ARCH-7: A Class-based Implementation of the OERA
OpenEdge Reference ArchitectureCommon Infrastructure
PresentationPresentation
Business ComponentsBusiness Components
Data AccessData Access
Data SourcesData Sources
Co
mm
on
Infrastru
cture
Co
mm
on
Infrastru
cture
Enterprise ServicesEnterprise Services Core Services• Auditing…
ABL Managers• Authorization
• Context Management
© 2007 Progress Software Corporation37 ARCH-7: A Class-based Implementation of the OERA
The Service Manager
© 2007 Progress Software Corporation38 ARCH-7: A Class-based Implementation of the OERA
The role of the Service Manager
CLASS service.servicemgr INHERITS base.manager IMPLEMENTS interfaces.iservicemgr, interfaces.icomponent:
DEFINE TEMP-TABLE ttSessionComponent NO-UNDO FIELD ComponentName AS CHARACTER FIELD ComponentType AS CHARACTER FIELD ComponentRef AS progress.lang.object FIELD SINGLETON AS LOGICAL. …METHOD PUBLIC progress.lang.object startService (pcComponentName AS CHARACTER, pcComponentType AS CHARACTER):
FIND FIRST ttSessionComponent WHERE ttSessionComponent.ComponentName = pcComponentName AND ttSessionComponent.ComponentType = pcComponentType NO-LOCK NO-ERROR. IF NOT AVAILABLE ttSessionComponent OR NOT ttSessionComponent.SINGLETON THEN RUN VALUE(cPackage + '/factory.p') (cClass, OUTPUT oObject, OUTPUT lSingleton NO-ERROR. RETURN (IF AVAILABLE ttSessionComponent THEN ttSessionComponent.ComponentRef ELSE ?). END METHOD.END CLASS.
© 2007 Progress Software Corporation39 ARCH-7: A Class-based Implementation of the OERA
Invoking Business Component Instances
Service
Manager
Service Interface
procedure
Business Component
class
Service Adapter
class
© 2007 Progress Software Corporation40 ARCH-7: A Class-based Implementation of the OERA
The role of the factory
/* samples/factory.p */DEFINE INPUT PARAMETER pcObject AS CHARACTER NO-UNDO.DEFINE OUTPUT PARAMETER objInstance AS progress.lang.object NO-UNDO.DEFINE OUTPUT PARAMETER plSingleton AS LOGICAL NO-UNDO.
CASE pcObject: WHEN 'becustomer' THEN DO: objInstance = NEW samples.becustomer(). plSingleton = YES. END. WHEN 'dacustomer' THEN DO: objInstance = NEW samples.dacustomer(). plSingleton = YES. END.END CASE.
You can’t create a class instance dynamically the way you can with RUN VALUE(…)• The compiler insists on knowing what’s going on!
The factory has a case for each possible object to create• Organized by package and object type
© 2007 Progress Software Corporation41 ARCH-7: A Class-based Implementation of the OERA
Using a factory procedure
Service
Manager
Service Interface
procedure
Business Component
class
Factory
procedure
Service Adapter
class
© 2007 Progress Software Corporation42 ARCH-7: A Class-based Implementation of the OERA
Alert! Planned (but of course not official) for 10.1C:
Service
Manager
Service Interface
procedure
Business Component
class
Service Adapter
class
DYNAMIC-NEW language extension will allow the Service Manager to instantiate classes directly using an expression for the class name.
© 2007 Progress Software Corporation43 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation44 ARCH-7: A Class-based Implementation of the OERA
Types of Context and State Information
Global context Application service context Client connection context
• These types can be persisted by a context manager
Client request context• This is transient information
• Does not need to be stored persistently
© 2007 Progress Software Corporation45 ARCH-7: A Class-based Implementation of the OERA
The context helper class
A complete implementation will have a context manager as Common Infrastructure• This can persist context for a session, for a
user, for the entire application
This implementation uses a context helper class to manage transient state information• This information is passed between client and
server as a context ProDataSet
© 2007 Progress Software Corporation46 ARCH-7: A Class-based Implementation of the OERA
ABL programming issues for the context class
The context class manages a ProDataSet instance and supporting methods
But you can’t pass an object (class instance) to the AppServer, only data
Therefore you have to extract the data and pass it to another object on the other side
© 2007 Progress Software Corporation47 ARCH-7: A Class-based Implementation of the OERA
Context helper class flow
Client Service Requester cltdatacontext.cls
DATASET dsContext
Service Adapter
Service Interface
srvdatacontext.cls
DATASET dsContext REF-ONLY
DATASET-HANDLE
from client
1
2
34
5
6
7
Create client context instance
Populate data Extract data Pass DataSet to
Service Adapter Pass to Service
Interface Create server
context instance Bind context to
DataSet passed from client
setContext
© 2007 Progress Software Corporation48 ARCH-7: A Class-based Implementation of the OERA
Agenda
OERA for SOBA and existing materials Overview of a class-based approach Server-side components Bridging the gap from client to server Using Templates Introducing Managers The Context Helper Class Generating Components from OE Architect Relational data in classes
© 2007 Progress Software Corporation49 ARCH-7: A Class-based Implementation of the OERA
Using the DataSet builder to generate data for a custom tool to use
© 2007 Progress Software Corporation50 ARCH-7: A Class-based Implementation of the OERA
Getting database data instead of an XMI file
© 2007 Progress Software Corporation51 ARCH-7: A Class-based Implementation of the OERA
Extending the OE Architect Menus
© 2007 Progress Software Corporation52 ARCH-7: A Class-based Implementation of the OERA
Generating Component source files
© 2007 Progress Software Corporation53 ARCH-7: A Class-based Implementation of the OERA
Code generation sample: the template
/*---------------------------------------------------------------------File : be<entity-name>.clsPurpose : Generated from the template for Business Entity classes Description : Sample Business Entity for <entity-name> Edited : April 2007 ---------------------------------------------------------------------*/ CLASS <package-name>.be<entity-name> INHERITS base.businessentity: {<package-name>/ds<entity-name>.i &REFERENCE-ONLY=REFERENCE-ONLY} CONSTRUCTOR PUBLIC be<entity-name>(): dataAccess = CAST (servicemgr:startService (‘<package-name>.da<entity-name>', "da"), <package-name>.da<entity-name> ). END CONSTRUCTOR.…END CLASS.
© 2007 Progress Software Corporation54 ARCH-7: A Class-based Implementation of the OERA
Code generation sample – the result
/*---------------------------------------------------------------------File : beCustOrder.clsPurpose : Generated from the template for Business Entity classes Description : Sample Business Entity for CustOrderEdited : 04/04/07 ---------------------------------------------------------------------*/ CLASS Sports2000.CustOrder.beCustOrder INHERITS base.businessentity: {Sports2000.CustOrder/dsCustOrder.i &REFERENCE-ONLY=REFERENCE-ONLY} CONSTRUCTOR PUBLIC beCustOrder(): dataAccess = CAST (servicemgr:startService ('Sports2000.CustOrder.daCustOrder',"da"), Sports2000.CustOrder.daCustOrder). END CONSTRUCTOR.…END CLASS.
© 2007 Progress Software Corporation55 ARCH-7: A Class-based Implementation of the OERA
A live look at generating components from templates using OpenEdge Architect
Tools for Business Logic
© 2007 Progress Software Corporation59 ARCH-7: A Class-based Implementation of the OERA
In Summary
The layers of the OpenEdge Reference Architecture provide valuable structure that you can fill in without excessive effort• Using templates for standard component types
• Using general-purpose supporting code
Classes in ABL can help you define your structure and assure its integrity
Resolve design issues in ways appropriate to your needs
© 2007 Progress Software Corporation60 ARCH-7: A Class-based Implementation of the OERA
For More Information, go to…
PSDN – OE Principles• http://www.psdn.com/library/kbcategory.jspa?categoryID=230
Other Exchange sessions• ARCH-11: Building a Presentation Layer with Classes
• ARCH-5: Modeling with UML
• ARCH-12: Design Patterns
• ARCH-2: OERA Latest Thinking
• DEV-12: Object-Oriented Programming in ABL
© 2007 Progress Software Corporation61 ARCH-7: A Class-based Implementation of the OERA
Questions?
© 2007 Progress Software Corporation62 ARCH-7: A Class-based Implementation of the OERA
Thank you for your time!
© 2007 Progress Software Corporation63 ARCH-7: A Class-based Implementation of the OERA