Professional Documents
Culture Documents
What are the system events and operations? What do the system operations do?
Determining visibility Drawing design class diagrams Deciding on architectural issues Logical Architecture and UML Package Diagram
A layer is a very coarse grained grouping of classes, packages, or subsystems that has cohesive responsibility for the major part of the system Typical layers in an OO system includes
User interface Application logic and domain objects Technical service
The layers of an architecture represent vertical slices, while partitions represent a horizontal division of the relatively parallel subsystems of a layer.
UI Swing :System Cashier makeNewSale() : Cashier enterItem(id, quantity) description, total Domain endSale() ... makeNewSale() enterItem() endSale() ... ProcessSale Frame makeNewSale() enterItem() endSale()
the system operations handled by the system in an SSD represent the operation calls on the Application or Domain layer from the UI layer
Vertical Layers
Domain
Sales
Payments
Taxes
Technical Services
Persistence
Logging
RulesEngine
Horizontal Partitions
Widget for the Enter Item System Event under Process Sale use case
presses button
UI Layer
Domain Layer
:Register
presses button
UI Layer
:ProcessSale JFrame
3: t = getTotal
Domain Layer
:Register
s : Sale
Drawn on the basis of conceptual model (analysis class diagram) Show the choices in assigning responsibility to objects Decision for assigning the responsibilities are based on the flow of massages between the interacting objects. Use of patterns
Knowing
Knowing about private encapsulated data Knowing about related objects Knowing about the things it can derive or calculate
Ex: Sale is responsible for printing itself (doing) Sale is responsible for knowing its date
Sequence Diagram
: Register : Sale
Collaboration Diagram
direction of message
makePayment(cashTendered)
:Register
1: makePayment(cashTendered)
:Sale
1.1: create(cashTendered)
:Payment
Creator
Problem: Who should be responsible for creating a new instance of some class? Solution: Assign class B the responsibility to create an instance of class A if one of the following is true
B aggregates A objects (Whole-part relationship) B Contains A objects B records instances of A objects B closely uses A objects B has the initializing data that will be passed to A when it is created (B is an expert with respect to A)
Contains 1..*
SalesLineItem quantity
* Sale aggregates many SalesLineItem objects. Create Pattern suggest that sale is a good candidate to have the responsibility of creating it described by 1 Product Spec description price code
: Sale
sli: SaleLineItem
Information Expert
Problem: What is a general principle of assigning responsibilities to objects? Solution: Assign the responsibility to the information expert- the class that has information necessary to fulfill the responsibility.
Described-by
t = getTotal
Sale
getTotal()
this notation will imply we are iterating over all elements of a collection
t = getTotal
: Sale
1 *: st = getSubtotal
lineItems[ i ] : SalesLineItem
t = getTotal
: Sale
1 *: st = getSubtotal
lineItems[ i ] : SalesLineItem
1.1: p := getPrice() Class Sale SalesLineItem Responsibility Knows Sales Total Knows line item sub total :Product Description
ProductDescription Knows product price Product Description SalesLineItem quantity getSubtotal() New method getPrice () description price itemID
Low Coupling
Problem: How to support low dependency and increase reuse? Solution: assign a responsibility so that coupling remains low.
A class with weak coupling does not depend on too many other classes
1: create() p : payment
Design 1
makePayment() 2: addPayment(p) : Register :Sale
1: makePayment() :Sale
Design 2
(Low Coupling) makePayment() : Register
1.1:create() p : payment
High Cohesion
Problem: How to keep objects focused, understandable, and manageable, and as a side effect, support Low Coupling? Solution: Assign a responsibility so that cohesion remains high. Use this to evaluate alternatives.
What first object beyond the UI layer receives and coordinates (controls) system operation? Assign the responsibility for handling a system event to a class representing one of the following choices
Represents the overall system (Faade Controller) Represents over all business organization (Faade controller) Represents something in the real world that is active (For example, the role of a person) that might be involved in the task (role controller) Represents an artificial handler of all system events of a use case (use case/session controller)
Controller
System Operations: Major input event generated by external actor Controller: is a non-user interface object responsible for handling a system event
presses button
UI Layer
Domain Layer
: ???
Which class of object should be responsible for receiving this system event message? It is sometimes called the controller or coordinator. It does not normally do the work, but delegates it to other objects. The controller is a kind of "facade" onto the domain layer from the interface layer.
Choice of the most appropriate controller depends on the factors like cohesion and coupling.
enterItem(id, quantity)
:Register
enterItem(id, quantity)
:ProcessSaleHandler
Register
HandleReturns Handler
allocation of system operations during design , using several use case controllers
Bloated Controller
A Controller handling too many responsibilities (Low Cohesion) Sign of Bloated Controller
A single controller receiving all system events, Low cohesion Too many attributes
Solution
More controller Single controller that delegates the responsibility to other objects
1: desc = getProductDesc(id)
by Expert
:Register
s :Sale
by Controller
by Expert
tot = getTotal
:Sale
1 * [i = 1..n]: st = getSubtotal
:ProductDescription
tot = getTotal
:Sale
1 *[ i = 1..n]: st = getSubtotal
:ProductDescription
makePayment(cashTendered)
:Register
1: makePayment(cashTendered)
:Sale
Logging a sale
Sale ... ... ... ... Sale
*
Logs-completed5 1 Store ... addSale(s : Sale) ... ... Logs-completed5
*
1 SalesLedger
Store is responsible for knowing and adding completed Sales. Acceptable in early development cycles if the Store has few responsibilities.
SalesLedger is responsible for knowing and adding completed Sales. Suitable when the design grows and the Store becomes uncohesive.
makePayment(cashTendered)
:Register
1: makePayment(cashTendered)
s :Sale
1.1: create(cashTendered)
:Payment
completedSales: List<Sale>
bal = getBalance
s :Sale
1: amt = getAmount
pmt: Payment
2: t = getTotal
completedSales {ordered}
*
payment 1 ...
Register Design Model DCD; software perspective ... endSale() enterItem(...) makePayment(...) 1
Determining Visibility
Visibility is the ability of one object to see or have reference to another. For an object A to send message to an object B, B must be visible to A
: Register
: ProductCatalog
Attribute visibility
Relatively permanent in nature
ProductCatalog is an attribute of Register. Because register needs to send getProductDescription message to catalog ProductCatalog exists as long as Register exists
class Register { ... private ProductCatalog catalog; ... } public void enterItem(itemID, qty) { ... desc = catalog.getProductDesc(itemID) ... }
: Register
: ProductCatalog
Parameter Visibility
Relatively temporary visibility
Persists within the scope of the method
enterItem qty) (id, :Register 2: makeLineItem (desc, qty) :Sale
1: desc = getProductDescid) ( 2.1: create(desc, qty) :Product Catalog makeLineItem(ProductDescription desc, int qty) { ... sl = new SalesLineItem (desc ,qty); ... } sl : SalesLineItem
Global Visibility
Least used Least desirable Assign an instance to a global variable
Records-sale-of Product Description Contains 1 1 0..1 Sales LineItem 1 Recordsaccountsfor 1 Used-by Describes 1..*
Ledger
Product Catalog
*
Store Stocks 1 1
*
Item
1..*
Houses
1.. * Register
*
Captured-on 0..1 1
Paid-by 1 CashPayment
Is-for 1 Customer
Records-sale-of Product Description Contains 1 1 0..1 Sales LineItem quantity 1..* Contained-in 1 Sale dateTime / total 1 Paid-by 1 CashPayment amountTendered 1 Is-for 1 Customer id Logscompleted 1 Recordsaccountsfor 1 Used-by 1..* itemID description price Describes
Ledger
Product Catalog
*
Store Stocks name address 1 1
*
Item
1..*
Houses
*
Captured-on 1 0..1
completedSales {ordered}
*
payment 1 ...
Application Layer
Tasks or rules that governs the process
Storage Layer
Persistent storage mechanism
Physical deployment
Client-server environment
Packages
Group of elements that provide a common service (or a family of related services), with relatively high coupling and collaboration. At a higher level of abstraction the elements are highly cohesive (strongly correlated responsibility)
Storage
Database
Layers
Core Elements
Sales
Product
Service Security
Database Interface
Communic ation
Reporting
partitions
Goal: When the total of the sale changes, refresh the display with the new value
{ propertyListeners.add( lis ); }
Sale addPropertyListener( PropertyListener lis ) publishPropertyEvent( name, value ) setTotal( Money newTotal ) ... { total = newTotal; publishPropertyEvent( "sale.total", total ); } javax.swing.JFrame ... setTitle() setVisible() ... propertyListeners
{ if ( name.equals("sale.total") ) saleTextField.setText( value.toString() ); } SaleFrame1 onPropertyEvent( source, name, value ) initialize( Sale sale ) ... { sale.addPropertyListener( this ) ... }
UML notation: Note this little expression within the parameter. This is legal and consise.
Sale addPropertyListener( PropertyListener lis ) publishPropertyEvent( name, value ) setTotal( Money newTotal ) ... publishes events to observers/listeners/ subscribers registers them when they ask to subscribe
propertyListeners
Polymorphism
Problem: How to handle alternatives based on type? How to create pluggable software components? Solution: When alternatives or behavior vary by type (class), assign responsibility for the behaviour-using polymorphic operations to the types for which the behaviour varies. Alternatives based on type
Avoiding conditional variation within the program using if-thenelse or case structure
TaxMasterAdapter
GoodAsGoldTaxPro Adapter
By Polymorphism, multiple tax calculator adapters have their own similar, but varying behavior for adapting to different external tax calculators.These are not the third party
software, but an interface that connects to the third party software
Pure Fabrication
Problem: Who should take the responsibility when you do not want to violate High Cohesion and Low coupling or other goals, but the solution provided by the expert is not appropriate ? Solution: Assign a high cohesive set of responsibilities to an artificial class that does not represent any thing in the problem domain. Ex: Saving sales in a database
Sale class has the necessary information to store itself. But
Sale class has to be coupled with relational database interface (not a domain level concept) Type of relational database may change in the future
Persistent Storage
Insert(Object) Update(Object)
By Pure Fabrication
Indirection
Problem: How to avoid direct coupling? How to decouple objects so that Low Coupling is supported and the reuse potential remains high? Solution: Assign the responsibility to mediate between the other components or services so that they are not directly coupled. The intermediary creates an indirection between the other components or services.
:TaxMasterAdapter
...
actor :TaxMasterSystem
Strategy
Problem: How to design for varying but related, algorithms or policies? How to design for the ability to change these algorithms or policies? Solution: Define each algorithm/policy/ strategy in a separate class, with a common interface.
AbsoluteDiscount OverThreshold PricingStrategy ... discount : Money threshold : Money getTotal( s:Sale ) : Money ...
??? PricingStrategy
{ pdt := s.getPreDiscountTotal() if ( pdt < threshold ) return pdt else return pdt - discount }
+ Sale
+ Register
...
visibility of the package element (to outside the package) can be shown by preceding the element name with a visibility symbol
POSRuleEngine
+ POSRuleEngineFacade instance : RuleEngineFacade getInstance() : RuleEngineFacade isInvalid( SalesLineItem, Sale ) isInvalid( Payment, Sale ) ...
...
- Rule1 ...
- Rule2 ...
State
Problem: An objects behavior is dependent on state. Conditional logic is undesirable because of complexity, scalability or duplication. What to do? Solution:
Create a class for each state that influences the behavior of the sate dependent objects (the context object) Based on the polymorphism, assign methods to each state class to handle the behaviour of the context object When the state dependent message is received by the context object forward it to the state object.
Command
Problem: A variety of requests or commands can be received by an object or system. How to reduce the receivers responsibility in handling the commands, increase the ease with which new commands may be added, and provide a foundation for logging, queuing and undoing commands? Solution: For each command, define a class that represents it and give it responsibility for executing itself.