Object Oriented Analysis and Design

Download Report

Transcript Object Oriented Analysis and Design

GRASP: Designing Objects
With Responsibilities
Chapter 17
Applying UML and Patterns
-Craig Larman
Designing Objects With Responsibilities
“Identify requirements, create a domain model and define
dynamic behaviour , define messages to meet
requirements , add methods to the software classes …”
 Too Simple!
 How do we assign responsibilities to classes?
 What methods belong where?
2
Object Design : Input


Use case text
•
System sequence diagram
•




Defining the behavior
Identifying the system operation messages
The operation contract
•
Stating events to design for, and detailed post-condition to satisfy
Supplementary specification
•
Defines non-functional goals
Glossary
•
Data format, data related with UI and database
Domain model
•
initial attempt of software object in the domain layer of software
architecture
3
Sample UP Artifact Relationships
Domain Model
Sale
Business
Modeling
Sales
LineItem
1..*
1
date
...
...
...
quantity
Use-Case Model
Process Sale
Process
Sale
use
case
names
Cashier
Requirements
Use Case Diagram
starting events to
design for, and
detailed postcondition to
satisfy
Design
non-functional
requirements
functional
requirements
that must be
realized by
the objects
Use Case Text
system
events
ideas for
the postconditions
inspiration for
names of
some
software
domain
objects
Supplementary
Specification
1. Customer
arrives ...
2. ...
3. Cashier
enters item
identifier.
domain rules
: System
Glossary
Operation:
enterItem(…)
Post-conditions:
-...
: Cashier
system
operations
make
NewSale()
enterItem
(id, quantity)
item details,
formats,
validation
System Sequence Diagrams
Operation Contracts
Design Model
: Register
: ProductCatalog
enterItem
(itemID, quantity)
d = getProductDescription(itemID)
addLineItem( d, quantity )
Register
ProductCatalog
...
makeNewSale()
enterItem(...)
...
...
*
1
getProductDescription(...)
...
Fig. 17.1 UP artifacts influencing OO design
: Sale
Responsability Driven Design-RDD
Design of behavior implies assigning responsibilities to software
classes.
Responsibilities are assigned to classes of objects during object
design.
Responsibility is a contract or obligation of a class
•
•
What must a class “know”? [knowing responsibility]
What must a class “do”? [doing responsibility]
5
Doing Responsability
What must a class “do”? [doing responsibility]
 Take action (create an object, do a calculation)
 Initiate action in other objects
 Control/coordinate actions in other objects
Doing responsibilities are implemented by means of methods
Methods fulfill responsibilities alone or through collaboration with other
objects and methods.
Ex: A Sale is responsible for creating SalesLineItems” (doing)
6
Responsibilities and methods : create
: Sale
makePayment(cashTendered)
create(cashTendered)
abstract, implies Sale objects have a
responsibility to create Payments
Sale objects are given a responsibility to create Payments.
The responsibility is invoked with a makePayment message
: Payment
knowing responsibility
What must a class “know”? [knowing responsibility]
•
•
•
Private encapsulated data
Related objects
Things it can derive or calculate
Knowing responsibilities are related to attributes, associations in
the domain model.
Domain model illustrates attributes and associations => inspires the
“knowing” responsibilities.
Ex : a Sale is responsible for knowing its total” (knowing)
8
Responsibilities and attribute
getDueDate message implies
Book has responsibility for
knowing its due date.
d := getDueDate()
:Book
9
RDD and Collaboration
Responsibilities are implemented by methods
Some methods act alone and do a task
Some collaborate with other objects to fulfill their responsibility.
Example:
Sale class has getTotal() method, the getTotal() collaborates
with SalesLineItem objects to get the subtotal through
getSubtotal() methods
10
Software pattern
What is a software pattern?
A design pattern is a general reusable and
proven solution to a commonly occurring
problem in software design.
Craig Larman: “ a pattern is a named
problem/solution pair that can be applied in
new contexts, with advice on how to apply it in
novel situations”
11
Well‐known Pattern Families
GRASP = General Responsibility Assignment Software
Patterns
Describe fundamental principles for assigning
responsibilities to classes and for designing
interactions between classes
GoF: Gang of Four Design Patterns : 23 pattrens
We’ll cover with GRASP
12
GRASP Patterns
9 GRASP patterns , but we start with the first five
• Information Expert
• Creator
• Controller
• Low Coupling
• High Cohesion
• Polymorphism
• Pure Fabrication.
• Indirection.
• Don’t Talk to Strangers
13
Creator
Creator principle
• Problem: Who creates an A object
• Solution: Assign class B the responsibility to
create an instance of class A if one of these is
true
B “contains or aggregate ” A
B “records” A
B “closely uses” A
B “ has the Initializing data for ” A
15
Creator principle
B “has the Initializing data for ” A that will be passed to
A when it is created.
• Often initiation is done using a constructor with
•
parameters.
e.g. a Payment instance, when created
needs to be initialized with the Sale total.
Sale class knows Sale total. Good candidate for
creating Payment is Sale.
If more than one of the above applies, prefer a class B
which aggregates or contains A.
16
Creator Pattern in Monoply
17
Problem
Who should create a SalesLineItem?
Sale
time
1
Contains
1..*
Sales
LineItem
quantity
*
Described-by
1
Product
Description
description
price
itemID
19
Creating a SalesLineItem
: Register
: Sale
makeLineItem(quantity)
create(quantity)
: SalesLineItem
Sale objects are given a responsibility to create SaleLineItem.
The responsibility is invoked with a makeLineItem message
Creating a SalesLineItem
21
Why Catalog is reating a Book ?
by Creator
makeBook(title)
:Catalog
1: create(title)
:Book
Information Expert
Information Expert
Problem : What is a basic principle by which to assign
responsibilities to objects?
Solution (advice ) : Assign a responsibility to the information
expert , that is the class with the information necessary
to fulfill the responsibility.
“Objects do things related to the information they have.”
Applying Expert in POS Application

Start assigning responsibilities by clearly stating the
responsibility.
Who should be responsible for knowing the grand
total of a sale?
Who should be responsible for knowing/getting the grand
total of a sale?
Sale
time
1
Contains
1..*
Sales
LineItem
quantity
*
Described-by
1
Product
Description
description
price
itemID
Who responsible for knowing the grand total of a sale?
27
Partial interaction and class diagrams
t = getTotal
Sale
:Sale
time
...
New method


getTotal()
Add a Sale class to the Design Model.
Express responsibility of knowing the total of a sale with the method named getTotal.
What information do we need to know to determine the line item
subtotal?
Sale knows about neighbours (associations), SaleLineitems who is
responsible for knowing its subtotal
SalesLineItem is Expert for Subtotal
this notation will imply we
are iterating over all
elements of a collection
Sale
time
...
t = getTotal
: Sale
1 *: st = getSubtotal
lineItems[ i ] :
SalesLineItem
getTotal()
SalesLineItem
quantity
New method
getSubtotal()
How does the SalesLineItem find out the product price?
SaleLineItem knows about neighbours ( ProductDescription) to
get the price.
ProductDescription is Expert for Price
Sale
time
...
t = getTotal
: Sale
1 *: st = getSubtotal
lineItems[ i ] :
SalesLineItem
1.1: p := getPrice()
getTotal()
SalesLineItem
quantity
:Product
Description
getSubtotal()
Product
Description
description
price
itemID
New method
getPrice()
“Partial” information experts collaborate to fulfill the responsibility.
Another Example
What class should be responsible for
knowing a resource, given a call number?
Catalog is an information expert on
finding and returning a resource,
based on a call number. It logically
contains all of them.
borrowResource(callNum)
:Library
1: r := getResource(callNum): Resource
:Catalog
by Expert
31
Low Coupling Principle
“Low Coupling” Principle
Problem:
How to support low dependency, Low change
impact, and increased reuse?
Solution: Assign responsibilities so that coupling
remains low. Use this principle to evaluate alternatives.
Coupling is a measure of how strongly one class is
• connected to,
• has knowledge of, or
• relies upon other classes.
33
What is a coupling ?
Coupling between classes is dependency of one class
on another class
Common form of coupling from Class A to Class B are:
 Class A has an attribute (data member or instance
variable) that refers to a Class B instance, or
Class B itself.
34
What is a coupling ?
Common form of coupling from Class A to Class B are:
 Class A has a method which references an
instance of Class B, or Class B itself, by any
means. These typically include a parameter or local
variable of type Class B, or the object returned
from a message being an instance of Class B.
35
What is a coupling (continued) ?
Common form of coupling from Class A to Class B are:
 Class A is a direct or indirect subclass of Class B.
 Class B is an interface, and Class A implements
that interface.
36
Common Forms of Coupling in OO Languages





Type X has an attribute (data member, instance variable) that
refers to type Y or an instance of Y.
An object of type X calls on services of a type Y object.
Type X has a method that references an instance of type Y
(e.g., parameter, local variable, object returned from a
method).
Type X is a subclass of type Y.
Type X implements the interface Y.
Low Coupling - POS Case Study

What class should be responsible for creating a
Payment instance and associating it with the Sale?
• Register?
• Sale?

Creator pattern suggests Register should create the
Payment.
• A register records a payment in the real world.
What if Register creates Payment
makePayment()
: Register
1: create()
2: addPayment(p)

p : Payment
:Sale
Register is coupled to both Sale and Payment.
What if Sale creates Payment ?
makePayment()
: Register
1: makePayment()
:Sale
1.1. create()
:Payment

Assuming that the Sale must eventually be coupled to
knowledge of a Payment, having Sale create the Payment
does not increase coupling.
NB : Low Coupling and Creator may suggest different
solutions.
Controller Pattern
Controller Pattern
UI layer does not contain any business logic
Problem:
How to connect UI layer to the business logic layer?
Solution:
If a program receive events from external sources
other than its graphical interface, add an event class
to decouple the event source(s) from the objects
that actually handle the events.
42
Controller Pattern
What first object beyond the UI layer receives
and coordinates (“controls”) a system
operation message?

Solution: Assign the responsibility to a class that
represents one of the following options:
Options for Control Responsibility
1.
2.
Represents the overall system or a root object.
e.g., an object called System or Register
Suitable when there are not too many system events
or when UI cannot choose between multiple controllers.
A controller for each use case
e.g. processSaleHandler
Controller choices ?
Controllers
enterItem(id, quantity)
enterItem(id, quantity)


:Register
:ProcessSaleHandler
Register (POS Terminal) is a specialized device with
software running on it.
ProcessSaleHandler represents a receiver of all system
events of a use case scenario.
What should be Controller for enterItem?
presses button
: Cashier
actionPerformed( actionEvent )
UI Layer
:SaleJFrame
system operation message
enterItem(itemID, qty)
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.
Bad Design
presses button
Cashier
actionPerformed( actionEvent )
UI Layer
:SaleJFrame
It is undesirable for an interface
layer object such as a window to get
involved in deciding how to handle
domain processes.
Business logic is embedded in the
presentation layer, which is not useful.
Domain Layer
SaleJFrame should not
send this message.
1: makeLineItem(itemID, qty)
:Sale
Good Design
presses button
: Cashier
actionPerformed( actionEvent )
UI Layer
system operation message
:SaleJFrame
1: enterItem(itemID, qty)
controller
Domain Layer
:Register
1.1: makeLineItem(itemID, qty)
:Sale
Controller should delegate the work that needs to be done to other objects.



Use Case Controller
A use case controller handles system events for
a single use case.
• Can maintain information about the state of
the use case.
• Different controller for each use case.
Not a domain object, but artificial construct to
support the system.
Use when there are many system events.
• Factors handling into separate classes.
Controller
role controller
borrowResource(callNum)
:Librarian
use case controller
borrowResource(callNum)
:BorrowResource
Handler
Controller: Benefits
Increased potential for reuse
Ensures that the application logic is not handled in the interface layer.
Thus, the external event raisers are independent of internal event
handlers
Plug & Play interfaces
Since the interface is not bound to the controllers, it can be replaced or
updated without much impact
Verifying the reasoning of the use case
Allows us to verify that the system operations occur in a logical
sequence. For example: makePayment() is not called before endSale()
51
High Cohesion
High Cohesion
A class with low cohesion does too much unrelated
work and are:
• Hard to comprehend
• Hard to reuse.
• Hard to maintain.
• Delicate and constantly affected by change
Cohesion is a measure of how strongly related the responsibilities of
an element (classes, subsystems) are.
53
High Cohesion

Problem
• How to keep complexity manageable?

Solution
• Assign a responsibility so that cohesion remains high
Reduced cohesion of Register(creator pattern)
: Register
: Sale
makePayment()
create()
p : Payment
addPayment( p )
Low cohesion:
Register is taking part of the responsibility for fulfilling “makePayment” operation
and many other unrelated responsibility ( 50 system operations all received by
Register).then it will become burden with tasks and become incohesive
Better solution
Higher Cohesion and Lower Coupling
: Register
: Sale
makePayment()
makePayment()
create()
: Payment
Solution:
Delegate the payment creation responsibility to “Sale” to support high cohesion
Conclusion


Like Low Coupling, High Cohesion is a
principle to keep in mind during all design
decisions
It is important to evaluate design
constantly with respect to GRASP
principles, regardless of the design result.
57
Object Design: startUp

Initial system operation

Delay until all other system operations have been considered

What objects need to be there through out the use case

What associations need to be there through out the use case

Create a set of domain objects that need to be there to support the
use


case execution
Find a suitable initial object and request that object to create a set of
other objects

Do the initialization design last
58
Object Design Examples
with GRASP
Chapter 18
Applying UML and Patterns
Craig Larman
60
Use-Case Realizations

UML interaction diagrams are used to
illustrate use-case realizations.

Design operations of the SSD

Principles and Patterns can be applied
during this design work.

Which object has which responsibility?
Domain Model and Use-Case
Realization

Some of the software objects that interact via messages in
the interaction diagrams are inspired from the Domain
Model.
• The
existing domain model is not likely to be perfect.
Errors and omissions are to be expected.
• You
will discover new conceptual classes that were
previously missed, ignore conceptual classes that were
previously identified, and do likewise with associations
and attributes.
Interaction Diagrams

Your System Sequence Diagram list the
system events.

Create a separate diagram for each system
operation(all events of the use case) under
development in the current iterative step.

If the diagram gets complex, split it into
smaller diagrams.
Multiple Sequence Diagrams (

Multiple sequence diagrams and system
event message handling.
Use-case Realizations for
NextGen Iteration

Explore the choices and decisions made
while designing a use-case realization, with
objects based on the GRASP patterns.
• No magic in the creation of well designed
•
ID’s.
Construction of ID’s is made on justifiable
principles.
System Operations of POS Application
66
Interaction Diagrams and
System Events

In the current iteration of PoS application, we
are considering two use-cases and their
associated system events:
 Process Sale
 makeNewSale
 enterItem
 endSale
 makePayment
 Start Up !!!!!!!
 startUp
Object Design : Contract
Name : makeNewSale()
 Responsibilities : Make a new sale for a cashier
to request to start a new sale, after a customer
has arrived with things to buy.
 Cross-References: Use Cases : Process Sale
 Pre-Conditions : None
 Post-Conditions : A sale instance was created.
The sale instance was associated with the
register . Attributes of the sale instance were
initialized.

Choosing the Controller Class
Our design choice involves choosing the
controller for the system operation message
 Here are some choices:
• Represents the overall system, device, or
subsystem: Register,
• Represents a handler of all system events of
a use-case scenario : ProcessSaleHandler.
 From those choices, we choose the register as
our controller

Creating a New Sale


A software sale object must be created, and
the GRASP creator pattern suggests
assigning the responsibility for creation to a
class that aggregates, contains, or records
the object to be created.
The register is a good choice to create the
sale object by the creator pattern.
Creating a New Sale
Object Design : enterItem




Name: enterItem(itemID : itemID,quantity :
integer)
Responsibilities : Enter sale of an item and
add it to the sale. Display the item description
and price.
Cross References : Use-Cases :
ProcessSale.
Pre-Conditions : There is an underway sale.
Object Design : enterItem

Post-Conditions
• sli was associated with current sale.(association
•
•
formed)
sli.quantity became quantity.(attribute
modification)
sli was associated with a ProductSpecification,
based on itemID match.(association formed), that
is also should find its ProductSpecification
Creating a new SalesLineItem


The contract post condition indicate a
responsibility to create a SalesLineItem
instance.
A Sale contains SalesLineItem objects.
• By creator pattern, the sale is an appropriate
candidate for creating Lineitems.

GRASP creator pattern
• Assign the responsibility for creation to a class
that aggregates, contains or records.
Finding a product specification



The SalesLineItem needs to be associated with
the ProductSpecification that matches the
incoming itemID.
Who should be responsible for looking up
the ProductSpecification based on the itemID
match?
By the Expert pattern, ProductCatalog is a
good candidate for the responsibility, since it
logically contains all the ProductSpecifications.
Visibility to a product catalog

Who should send the Specification message to the
ProductCatalog to ask for a ProductSpecification?
• Assumption: A Register and a ProductCatalog
instances were created during the initial Start Up
use-case, and there is a permanent connection
between them.

Based on this assumption, then it is possible to the
Register to send the specification message (using
reference to productCatalog) to the
ProductCatalog.
Object Design : endSale
Contract






Name : endSale()
Responsibilities : Record that it is the end of
entry of sale items, and display sale total.
Cross References : Use Cases : Process
Sale
Exceptions : If a sale is not underway,
indicate that it was an error.
Pre-Conditions : There is an underway sale.
Post-Conditions : sale.isComplete became
true.
Choosing the Controller Class

Based on the Controller Pattern, as for
enterItem, we will continue to use register as
a controller.
Setting the Sale.isComplete
attribute
We will continue to use register as a controller
The contract post-condition state:
 Sale.isComplete became true.
 As always, Expert should be the first pattern
considered unless it is a controller or creation
problem (which is not).
 Who should be responsible for setting the
Sale.isComplete attribute of the Sale to true.
• By Expert, it should be the Sale itself.
Communication Diagram :
endSale

Setting the Sale.isComplete attribute (2)
Constraints and Notes
Object Design:makePayment
Choosing the Controller Class
 Based on the Controller GRASP pattern, as
for enterItem, we will continue to use
Register as a controller.
 It is common to use the same controller
throughout a use case.
Creating the Payment

Register – makePayment Communication
diagram
Logging the Sale
Who should be responsible for knowing the
complete sale.
Logging a completed sale




Perhaps we did not think of a sale ledger
early, but now we have.
If it is not chosen, it would be ideally
added to the domain model as well.
Fortunately, iterative development
provides a life-cycle for continual
change.
This kind of discovery and change during
design work is to be expected.
Logging a Completed Sale
Calculating the Balance
Who is responsible for knowing the balance?
 To calculate the balance, the Sale and
Payment cash tendered are required.
 Therefore, Sale and Payment are partial
experts for solving the problem.
Calculating the Balance
Questions ?
91