Transcript Document

Architectural Analysis & Design
Architectural Layers
The Logical Architecture is a large-scale organization of the software classes
into packages (or namespaces), subsystems, and layers. Decisions about how
these elements are to be deployed across physical computers in a networked
environment are part of the Deployment Architecture.
Classes in the system are grouped into layers. A layer is a coarse-grained
grouping of classes, packages, or subsystems that has cohesive responsibility for
a major aspect of the the system. Layers are organized so that “higher” layers
call upon services of “lower” layers, but not generally vice-versa.
Architectural Analysis & Design
Architectural Layers
•User Interface
The user interface with the system may be through a graphical user interface
or through web-based services. The user interface may consist of packages
such as the swing package and the web package, where the swing package
refers to the user generated classes that specialize the GUI framework
•Application Logic and Domain Objects
Software objects representing domain concepts. This layer may be
divided into an Application layer containing facades for maintaining
session state and controlling workflow to the Domain layer concpts.
•Technical Services
General purpose objects and subsystems that provide supporting
technical services such as forming an interface with a database.
Architectural Analysis & Design
Using layers helps address these problems:
•Source code changes are rippling throughout the system – many parts of the
system are highly coupled.
•Application is intertwined with user interface, so it cannot be reused with a
different interface or distributed to another processing node.
•Potentially general technical services or business logic is intertwined with more
application specific logic so it cannot be reused, distributed to another node, ore
easily replaced with a different implementation.
•There is high coupling across different areas of concern. It is difficult to divide
the work along clear boundaries for different developers.
Architecture Analysis & Design
GUI Windows, reports,
speech, XML, HTML,
JSP, Javascript
Handles presentation
layer requests, session
state, workflow
Handles application
layer requests,
implementation of
domain rules& services
Low-level business
services such as
currency conversion
Higher-level technical
services such as
persistence & security
Low-level technical
services, utilities and
frameworks such as
data structures, threads,
math, network I/O
dependency
UI
(AKA Presentation, View)
Application
(AKA Workflow, Process,
Mediation, ApplicController)
Domain
(AKA Bussiness, Application Logic)
Business Infrastructure
(AKA Low-level Business Services)
Technical Services
(AKA High-level Technical Services)
Foundation
(AKA Core Services, Base Services, Low-level
Technical Services)
Range of applicability
More
application
specific
Architecture Analysis & Design
Examples of UML notation for packages and layers
Domain
POS
Inventory
Tax
Security
Logging
Vertical layers
Technical Services
Persistence
Horizontal partitions
Package or
subsystem
Architecture Analysis & Design
Guideline: Model-View Separation Principle
1.
Do not connect or couple non-UI objects directly to UI objects. For
example, do not let a Sale object have a reference to a JFrame window
object. Windows are related to a particular application and platform,
whereas the Domain objects may be reused in a new application or
attached to a new interface.
2.
Do not put application logic (such as tax collection) in the UI object
methods. UI objects should only initialize UI elements, receive UI
events (such as mouse clicks), and delegate requests for application
logic to non-UI objects.
Architecture Analysis & Design
UI
Cashier
System
makeNewSale()
Swing
enterItem(id,qt)
…
makeNewSale( )
enterItem(id, quantity)
ProcessSale
Frame
endSale( )
makeNewSale()
enterItem(id,quant)
description, total
endSale( )
Domain
endSale( )
…...
Register
makeNewSale( )
enterItem(id, quant)
endSale( )
System Operations
shown in SSD
Implementation of System Operations
Designing a Persistence Framework
This presentation illustrates the design of a persistence
framework and the use of Design Patterns in constructing
that framework. There are free, open-source persistence
frameworks that you can use in your project. You do not
have to create one of your own. In the Java domain, there
is a widely used framework called Hibernate
(www.hibernate.org).
Design of a Persistence Framework
Domain Layer
Persistence Framework
Relational Database
PersistenceFacade
:University
name = Cornell
get(OID, class):Object
put(OID, object)
city = Ithaca
University
object
Domain object
will
dematerialize
when application
goes out of scope
Name
City
Harvard
Cambridge
Yale
New Haven
Michigan
Ann Arbor
Cornell
Ithaca
Store object in RDB
put(OID,
RetrievecornellObj)
from RDB
get(OID, University)
University Table
Accessing Persistence Service with a Facade
Facade Pattern
Intent Provide a unified interface to a set of interfaces in a subsystem.
Facade defines a higher-level interface that makes the subsystem easier to use.
Applicability
•You want to layer your subsystem. Use Facade to define an entry point to
each subsystem level.
•Introduce a Facade to decouple subsystems from clients and other
subsystems, thereby promoting subsystem independence and portability.
•A Facade can produce a simple default view of the subsystem.
Collaborations
Clients communicate with the subsystem by sending requests to Façade, which
forwards them to the appropriate subsystem object. Clients that use facade do
not have to acess subsystem objects directly.
The Facade Pattern
An Object Identifier Pattern
We need a consistent way to relate objects to records in a database
and be able to ensure that repeated materialization of a record does
not result in duplicate objects.
The Object Identifier Pattern proposes assigning an object
identifier (OID) to each record and each object (or proxy of
an object). An OID is an alphanumeric code that is unique
to each object.
Every table will have an OID as primary key
The Facade Pattern
Mapping between persistent object
and Database
University Table
OID
name
city
uxh345
Harvard
Cambridge
:University
uxy248
Yale
New Haven
name = Cornell
uxm117
Michigan
Ann Arbor
city = Ithaca
uxc123
Cornell
Ithaca
oid = uxc123
primary key
The OID may be contained in proxy
object instead
The Facade Pattern
:DBProductAdapter
:PersistenceFacade
pd = get(…)
PersistenceFacade
getInstance():Persistence
Facade
get(OID, class)
put(OID,Object)
//example use of the facade
OID = new OID(“XYZ123”);
ProductDescription pd = (ProductDescription)
PersistenceFacade.getInsance().get(oid, ProductDescription.class);
The Database Broker
What class should be responsible for the materialization and
dematerialization of the objects from a persistent store?
The Information Expert Pattern suggests that the persistent
object class itself have this responsibility – It has some of the
data (the data to be saved) required by the responsibility. This
is termed Direct Mapping.
Problems with the Direct Mapping approach include:
•Strong coupling of the persistent object class to persistent storage
knowledge – (violation of low coupling)
•Complex responsibilities in a new and unrelated area to what the object
was previously responsible for – (violation of high cohesion). Technical
service concerns are mixing with application logic concerns.
The Database Broker
Second option – use an indirect mapping approach.
Create a DatabaseMapper class that is responsible for the
materialization and dematerialization of objects from the
database. Each persistent object will have its own Mapper
class.
The Facade Design Pattern with Brokers
PersistenceFacade
getInstance( ):
PersistenceFacade
<<interface>>
DBMapper
class
get(OID, class) : Object
get(OID):Object
put(OID, Object)
put(OID, Object
ProductSpecification
RDBMapper
ProductSpecification
FlatFileMapper
Manufacturer
RDBMapper
get(OID):Object
get(OID):Object
get(OID):Object
put(OID, Object)
put(OID, Object
put(OID, Object
Each mapper gets and puts objects in its own unique way, depending
on the kind of data store and format.
Facade Pattern with Brokers
class PersistenceFacade {
public Object get (OID oid, Class persistenceClass ) {
DBMapper mapper = (DBMapper) mappers.get (persistencceClass);
//delegate
return mapper.get(oid);
}
public put (OID oid,, Object obj) {
Class persistenceClass = obj.getClass( );
DBMapper mapper = (DBMapper) mappers.get (persistencceClass);
mapper.put(oid, obj);
}
}
Designing the DatabaseMapper Classes
The Template Method pattern should be used to:
•Implement the invariant parts of an algorithm once and leave it to the
subclasses to implement the behavior that can vary.
•When common behavior among subclasses should be factored and
localized in a common class to avoid code duplication.
•To control subclass extensions.
AbstractClass
ConcreteClass
TemplateMethod( )
PrimitiveOperation1()
PrimitiveOperation1()
PrimitiveOperation2()
PrimitiveOperation2( )
{ …..
PrimitiveOperation1( );
……..
PrimitiveOperation2(); …}
Template Pattern
The Hollywood Principle:
“Don’t call us, we’ll call you!”
Example: The swing GUI framework
//unvarying part of algorithm
public void update {
clearBackground( );
//call the hook method
repaint( );
}
GUIComponent
framework class
update( )
Template method
repaint( )
hook method
MyButton
repaint( )
programmer’s class
hook method overridden
to supply class specific
detail
Template Method
Consider the POS Terminal Example
<<interface>>
DBMapper
get(OID):Object
put(OID):Object
Abstract
PersistenceMapper
+get(OID):Object {leaf}
#getObjectFromStorage( ):Object
template method
hook method {abstract}
Template Method
Overriding the hook method
//template method
public final Object get(OID oid) {
obj = cachedObjects.get(oid);
if (obj == null) {
//hook method
obj = getObjectFromStorage(oid);
cachedObject.put(oid, obj);
}
return obj;
}
DBMapper
AbstractPersistenceMapper
+ get(OID):Object {concrete}
# getObjectFromStorage(OID):Object
{abstract}
//hook method override
protected Object getObjectFromStorage(OID oid)
{
String key = oid.toString( );
ProductDescription
RDBMapper
dbRec = SQL execution result of
“Select* from PROD_DESC where key =“
+key
ProductDescription = new ProductDescription();
pd.setPrice(dbRec.getColumn(“PRICE”); etc
# getObjectFromStorage(OID):Object
Persistence Framework
NextGen Persistence
ProductDescription
RDBMapper
ProductDescription
FileWithXMLMapper
SaleRDBMapper
ProductDescription
InMemoryTestDataMapper
Persistence
PersistenceFacade
class
Abstract
RDBMapper
1
<<interface>>
DBMapper
Abstract
PersistenceMapper
Template Method
Implementation of Template Method in POSTerminal
public class PersistenceManager {
public final Object get(OID oid) {
//template method
obj:= chachedObjects.get(OID oid);
if (obj == null) {
//hook method
obj = getObjectFromStorage(oid);
cachedObject.put(oid, obj);
}
return obj;
}
public class ProductDescriptionRDBMapper extends
PersistenceManager {
protected Object getObjectFromStorage(OID oid) {
String key = oid.toString( );
dbRec = SQL execution result of
“Select * from PROD_DESC where key = “ + key
ProductDescription pd = new ProductDescription ();
pd.setOID(oid);
pd.setPrice ( dbRec.getColumn(“PRICE”) );
pd.setItemID ( dbRec.getColumn(“ITEM_ID”) );
pd.setDescription( dbRec.getColumn(“DESC”) );
return pd;
}
…….
}
protected abstract Object getObjectFromStorage(OID oid) ;
}
Transactional States and the State Pattern
Statechart for the PersistentObject
[new (not from DB)]
[from DB]
save
commit / insert
New
OldClean
rollback / reload
commit / update
OldDirty
delete
delete
rollback / reload
Deleted
commit / delete
OldDelete
State Pattern
Context/problem
An object’s behavior is dependent upon its state, and its
methods contain case logic reflecting conditional statedependent actions. Is there an alternative to conditional logic?
Solution
Create state classes for each state, implementing a common
interface. Delegate state-dependent operations from the
context object to the appropriate state object. Ensure the
context object always points to the state object reflecting its
current context.
State Pattern
Collaborations (Example)
TCPState
TCPConnection
Open( )
Open( )
Close( )
Close( )
Acknowledgement( )
Acknowledgement( )
state  open( )
TCPEstablished
TCPListen
TCPClosed
Open( )
Open( )
Open( )
Close( )
Close( )
Close( )
Acknowledgement( )
Acknowledgement( )
Acknowledgement( )
State Pattern
Applying the State Pattern to the Persistence Framework
PObjectState
PersistentObject
oid: OID
state: PObjectState
commit( )
delete( )
Rollback( )
save( )
setState(PObjectState)
state  commit( this );
1
*
OldDirty
State
commit (PersistentObject obj);
delete (PersistentObject obj);
rollback (PersistentObject obj);
save (PersistentObject obj);
OldClean
State
New
State
{//commit
PersistenceFacade.getInstance()
.update(obj)
obj.setState(OldCleanState.
getInstance()}
commit( …)
delete(…)
rollback(…)
delete(…)
save (…)
commit( …)
Persistent Objects
Domain
Persistence
ProductDescription
PersistentObject
oid: OID
timeStamp: DateTime
Sale
commit( )
delete( )
rollback( )
save( )
Whenever a Domain object class extends a Technical Services class it
should be done with hesitation and for a good reason. You will be mixing
application logic and the technical concern of persistence.
Architectural Design
Architectural Views
Conceptual organization of the Architecture in terms of subsystems,
•Logical
packages, frameworks, classes, and interfaces. Summarizes the
functionality of the major software elements.
•Process
Responsibilities, collaborations, and the allocation of responsibilty to
processes and threads.
•Deployment
Physical deployment of processes and components to nodes and the
network configuration between nodes.
Overview of the data flows, persistent data schema, and the mapping
•Data
from objects to persistent data.
Overview of the security schemes and points within the architecture
•Security
that security is applied.
actual source code and executables. A summary of noteworthy
•Implementation The
deliverables.
•Development
•Use Case
Summarizes information developers need to know about the setup of the
development environment – directory structure, version control, etc.
Summary of the most architecturally significant use cases and their nonfunctional requirements. Summary of those use cases that illustrate
significant architectural coverage or exercise many arch. elements.