Enterprise Component Authoring Principles and Design Patterns

Enterprise Component Authoring
Principles and Design Patterns
Authors
NS Nagaraj, Srinivas Thonse,
Naqvi, Mukulika
Members, Comfactory Group
Software Engineering and Technology Labs
Infosys Technologies Limited
Bangalore
Abstract
Object technology has evolved over many years yielding various design principles,
languages and environments producing a productive way of writing complex, large
applications. The introduction of COMponent models has eased the complexities of
developing distributed applications. The DNA model has evolved as the de-facto
reference architecture for enterprise applications. Enterprise component developers
have languages and environments that support both the idea of classes/objects and
components. Classes and components are two good constructs available, which when
used rightly produces software that is scalable, reusable and maintainable.
Give the enterprise need to develop applications for business process automation, it
is important for organizations to understand and evolve component authoring
principles and patterns. These should provide a reference standard for authoring
components. With our experience in constructing various large enterprise
applications on DNA (for Insurance, payroll, e-store), we have devised a set of
principles and patterns that occur quite often in enterprise solutions.
1. Component Granularity Principle (CGP) proposes a way to decide granularity
of components.
2. Lazy Construction of Components (LCC) proposes a useful design idea to
deal with User Interfaces that require large business objects from enterprise
application servers.
3. Business Object Editor Pattern: Enterprise applications often require User
Interface components for configuring and editing of business objects by
operators. This pattern is useful to design such components.
4. Lite-client and Worker Pattern (LCW) proposes a technique to improve the
maintainability of client-side components of n-tier applications. This is
accomplished by minimizing dependency of User Interface components on finegrained Business Objects.
©2000 Infosys All rights reserved.
1
1 Component Granularity Principle
Consider a simple order processing enterprise application, which provides interface
for accepting and processing of orders from users items from users. Let us say this
system needs to collect 1000 orders every minute and look at the fulfillment
possibility. If the order cannot be fulfilled then system will put this on back order list
and process later (on availability of inventory). From the application design angle
what would you model as Component/Classes?
If you examine the typical Order processing abstraction there are many elements like
item details, customer address, price details, shipment information, payment details,
Order processor.
If you model all the above abstractions as components then it will result as overengineered system with too many component instances leading to inefficient usage
of system resources (Imagine an Order containing 1000 Item components, in a peak
minute system will end up creating more than 1 million components).
Now the question is what should be Component and what should be Class?
Principle
“Fine grain Business Entities should be modeled using Class
construct, Business Services should be modeled using Component
construct”
Applying this principle Order processing system will lead to Business entities modeled
as Classes named Order, Item, Shipment, Address, Payment and Business Services
modeled as Components named OrderProcessor, ShipmentProcessor and Payment
Processor. This results in fewer components and optima l use of system resources.
©2000 Infosys All rights reserved.
2
2 Lazy construction of Components
2.1
Context
Enterprise applications have user interfaces made of text fields, radio buttons, check
boxes, selection lists, etc., that map to attributes of the business object being edited,
e.g. Customer, or, attributes of input required for business tasks such as approve
leave.
Many attributes of business objects are references or identifiers for static data such
as country codes, state codes and other business-specific codes. For e.g., Customer
object might have fields such as name, address and countryCode. Among these
fields, countryCode refers to a country in the country code data space. The User
interface needs to provide lists of such codes in combo boxes. A screen could contain
many such fields such as Country, States, Currency and so on. The user interface
requires that these lists be fetched and populated in the combo boxes. Bringing up a
form containing a large number of such lists would take significant time in fetching
the lists and populating the fields.
Some business objects are composites of other smaller business objects. Screens
meant for editing such business objects (“composite screens”) typically have several
tabs, where each tab shows data of one or a few of these contained objects. This
requires a solution to construct the screen in minimum time.
2.2
Solution
To reduce the initial time taken by the UI screen to load, we have adopted the
technique of lazy construction of components. The concept here is to fetch as little
data as needed before popping up the screen and to fetch the rest only as needed.
This means that all the combo-boxes are populated when the user clicks on a combo
box for the first time. In the case of composite screens, data shown in one or a few
tabs are fetched initially. Below a design for building such components is described.
2.2.1 Static list in Combo box
The policy for loading static data in the combo box is as follows: The combo boxes
are not filled with any data to start with, i.e. when the screen pops up, the combo
boxes is empty. When the user clicks on a combo box the data records pertaining to
that field are fetched in an object and also saved in a file in the local system. This
cached static data is marked with a time stamp. Every time, on the first click on the
combo box, a time stamp comparison is made between the cached data on the local
disk and that in the database on the server side. If the cached data is found to be
stale than the server data, the data is fetched from the server database; otherwise
the cac hed data is used. Moreover, the timestamp check and, if needed, the fetching
of data is accomplished in just one call to the server side. Below is the class design
of the “static data access component”.
Static data access component:
ListObject: This class contains data for a code type and for a key for e.g. the code
type could be state codes and key could be India. So the Recordset would contain
records for all the stated in India.
StaticDataLoader: The StaticDataLoader class is responsible for constructing the
ListObject
class
and
populate
it
with
data.
It
uses
the
classes
©2000 Infosys All rights reserved.
3
StaticDataCacheManager and StaticDataInterface to get the latest data either from
the cache or from the server.
StaticDataCacheManager: This class is used to cache the static code data retrieved
from the server.
StaticDataInterface: This class is a COM component. This is used to get the static
codes data from the server.
Class Diagram
ListObject
dataRS : RecordSet
getNext()
getRecordCount()
validateCode()
uses to populate combo boxes
creates and populates
UI Screen
static data interface
StaticDataLoader
for data from server
getListObject()
<<COM Component>>
StaticDataInterface
getStaticCodes()
uses for loading cached data
StaticDataCacheMana
ger
getUpdateTime()
getStaticCodes()
updateStaticCodes()
Sequence Diagram: Populating Combo boxes
©2000 Infosys All rights reserved.
4
The sequence
starts when a
user clicks on a
combo box on
the screen.
: UI Screen
:
StaticDataLoader
: ListObject
:
StaticDataCacheManager
:
StaticDataInterface
getListObject(String, List<String>)
getUpdateTime(String)
getStaticCodes(String, List<String>, String)
check the return value of getStaticCodes()
getStaticCodes(String, List<String>)
Called based on the
check performed.
i.e. if cache is found
to be up to date.
construct()
getRecordCount( )
getNext( )
2.3
Repeated calls to
populate combo
box.
Impact
The above design mechanism for displaying static data in the user interfaces will
result in the reduction in time of the initial loading. However, this wait time is not
completely eliminated but distributed across various user events like combo box
clicking. In many cases, it might be desired that the combo boxes be filled on loading
itself; or that some combo boxes be filled and some not. This mechanism is meant
for reducing the initial load time of the screen. However in both the cases, i.e.
immediate and lazy loading, the caching mechanism provided by the
StaticDataCacheManager can be used.
©2000 Infosys All rights reserved.
5
3 Business Object Editor Pattern
3.1
Context
3.2
Solution
Most of the enterprise applications require some kind of editors to add, delete, edit
or search business objects such as Customer, Country and Currency. Generally for
any Business object the editor provides the same set of functionalities like add,
delete, edit, search but the object properties that are displayed differ from object to
object. For e.g., the Business Object Editor for Customer or Equipment will have the
same set of functionalities but the properties of Customer are different from that of
Equipment. Thus we see a definite pattern can be followed to provide these
functionalities, the only difference will be the forms and the data.
For any business object editor, we can design the user interface to have a Master or
parent form that will have
1. Searcher part to specify the search criteria and search fields
2. An object list satisfying the search criteria
3. Option to add, edit, delete the selected object and save the changes in the
database. When an object is selected for editing or deleting, or a new object has
to be added, a child form comes up with all the details of the business object.
The child form should have ok, next and previous options.
a. On ok click it saves the changes made to the selected object.
b. On next or previous click it not only saves the changes but also displays
the details of next or previous object in the object list in the Parent form.
All these changes are saved locally
c. On save click, the changes are saved to the server.
Snapshots of Customer business object editor are given below.
©2000 Infosys All rights reserved.
6
©2000 Infosys All rights reserved.
7
3.2.1 Class Design
<<Interface>>
IView
IFormViewInteractor
oldObject
newObject
viewInteractor
addObject()
nextObject()
prevObject()
selectedObject()
inFirstObject()
changeObject()
clearAll()
setAllFields()
getparentView()
IMasterForm
search()
save()
clear()
ViewInteractor
CustomerChildForm
CustomerMasterForm
Apply()
PrevObject()
NextObject()
1..1
1..1
CustomerMasterDirectory
search()
save()
IView interface is implemented by the Master Form to interact with the Child form
through the ViewInteractor class.
IMasterForm interface is implemented by the Master Form to interact with it’s
MasterDirectory class to search and save business objects in the database.
IFormViewInteractor interface is implemented by the Child Form to interact with
the Master Form through the ViewInteractor class.
?? OldObject stores the object passed to the child form for change. It is NULL for
add mode.
?? NewObject gets populated with changed data on add , next or previous click.
MasterDirectory is implemented by every Business Object differently (e.g..
CustomerDirectory, EquipmentDirectory) to save and search different data from the
database. The search , save methods of this class are called by the Master Forms.
Although the implementation is different for different business objects the pattern
followed is the same.
The ViewInteractor class is used to interact between Master and child forms. It has
a reference to IFormViewInteractor interface of the child form as well as the IView
©2000 Infosys All rights reserved.
8
interface of the parent form. All interactions between child and parent form take
place through this class. It has the following functions
?? Apply
If the oldObject from child form is NULL i.e it is in add mode
Call ParentForm.addObject with the newObject
Else if child form has an oldObject i.e it is in edit mode
Call ParentForm.changeObject with newObject
Endif
?? NextObject
Call Apply
Get the nextObject from parent form
Assign it to oldObject of childForm
Populate child form with the values in oldObject
?? PreviousObject
Call Apply
Get the previousObject from parent Form
Assign it to oldObject of childForm
Populate child form with the values in oldObject
If the object selected is the first object in the object list of parent form
then
Disable previous button
Endif
3.2.2 Interaction between the Master and Child Forms
?? When Add/Edit clicked in Master Form
©2000 Infosys All rights reserved.
9
: Customer
MasterForm
: Customer
ChildForm
CustomerMaster
FormView : IView
: View
Interactor
: User
IView Interface of Master
Form , add/edit mode
and whether first object
selected ,is passed to
the child form.
Clicks add/edit
Load
oldObject=selectedObject( )
bFirstObject=inFirstObject( )
Populate(oldObject)
Child form is
populated if in edit
mode
new
OldObject
will be NULL
for add mode
Enabling, disabling
of previous button
depends on this
boolean
IFormView
Interactor interface
of child form is
passed to the
ViewInteractor
class
?? When Ok/Prev/Next clicked in Child Form
©2000 Infosys All rights reserved.
10
: Customer
ChildForm
: View
Interactor
: User
Ok/Prev/Next button click
Populate newObject with field values
Apply( )
1.Apply() is called for Ok
click
2.PrevObject() is called
for Prev click
3.NextObject() is called
for Next click
3.3
Impact
This pattern through mandating the use of interfaces brings about uniformity in the
user interface components. Repeated use of the classes and interfaces leads to
significant reuse of code, increased reliability and faster development. Code will be
less error prone and easier to maintain.
©2000 Infosys All rights reserved.
11
4 Lite Client and Worker pattern
4.1
Context
The client-side components of Enterprise Applications contain many invocations of
services from Server-side components. If the services are very large in number, the
compile-time dependencies of client components on server components become very
difficult to maintain. This leads to deployment issues during maintenance and
upgrades.
4.2
Solution
LCW pattern is a way to decouple the client and server to a large extent. The
requests for services are modeled as documents. The application server hosts
components called “Workers” which implement the processing function. The clients
request WorkerFactory for desired Workers by specifying the name of the worker
object. The WorkerFactory instantiates the required Worker object implementation
and returns a reference to the instance. The clients then prepare a request object
containing the request name and related information and invoke the processing
function on the worker instance. The worker instance performs the necessary
processing.
<<Interface>>
IWorker
execute(WorkRequest : Document)
<<Document>>
WorkRequest
WorkerFactory
<<implements>>
createWorker(name : string) : IWorker
set(name : String, number : integer)
getAsInt(name : string) : integer
set(name : string, value : string)
getAsString(name : string) : string
OrderProcessorWorker
creates
execute(action : WorkRequest)
©2000 Infosys All rights reserved.
12
UI
: User
1: submit
: Worker
Factory
: Order
Processor
work : Work
Request
2: createWorker("ÖrderProcessor")
3: new( )
4: new( )
5: set("RequestName", "Process Order")
6: set("name", "Smith")
7: set("item", ïtemName)
8: set("cardNum", crNo)
9: execute(work)
4.3
Impact
This pattern completely simplifies client-side programming. All the clients know
about is about names of Worker objects and the request contents required. If this
can be standardized (“contract”) at the start of the project, the user interface
development can run independent of server-side development. It becomes easy to
manage change when new versions of worker classes are released, through adding
request translation functions that transparently translate the request objects to the
new semantics. On the flip side, this adds an extra layer of indirection and requires
strict adherence of the contracts – more care by developers may be required.
©2000 Infosys All rights reserved.
13