Using Design Patterns With GRASP: G R A S P
Using Design Patterns With GRASP: G R A S P
The patterns provide a representation of nine basic principles that form a foundation for designing objectoriented systems.
Responsibility-Driven Design
Responsibilities of an Object include two types : Knowing and Doing
Doing responsibilities of an object include:
Doing something itself, such as creating an object or doing a calculation Initiating action in other objects Controlling and coordinating activities in other objects Knowing responsibilities of an object include: Knowing about private encapsulated data (know thyself, presume not God to scan) Knowing about related objects Knowing about things it can derive or calculate Responsibilities are an abstraction methods fulfill responsibilities Responsibilities are implemented by means of methods that either act alone or collaborate with other methods and objects. 2
Die
faceValue
MonopolyGame
Board
Player
name
Piece
name
Is-on 0..8 1
Square
name
+ B contains or completely aggregates A + B records A + B closely uses A + B has the initializing data for A
40
:Board
create
:Square
Alternative Design
Dog: Piece
s = getSquare(name)
:Board
Sqs: Map<Square>
sqs = getAllSquares(name)
Poor Design !
Board Piece squares Alternative Assign getSquare( name) to the Piece object {Map} getSquare getAllSquares More coupling if Piece has getSquare ( )
Square
Low Coupling
One of the the major GRASP principles is Low Coupling.
Coupling is a measure of how strongly one object is connected to, has knowledge of, or depends upon other objects. An object A that calls on the operations of object B has coupling to Bs services. When object B changes, object A may be affected.
Low Coupling How to reduce the impact of change? Assign responsibilities so that (unnecessary) coupling remains low. Use this principle to evaluate alternatives.
10
Low Coupling
Key Point: Expert Supports Low Coupling To return to the motivation for Information Expert: it guides us to a choice that supports Low Coupling. Expert asks us to find the object that has most of the information required for the responsibility (e.g., Board) and assign responsibility there. If we put the responsibility anywhere else (e.g., Dog), the overall coupling will be higher because more information or objects must be shared away from their original source or home, as the squares in the Map collection had to be shared with the Dog, away from their home in the Board.
11
Controller
A simple layered architecture has a user interface layer (UI) and a domain layer. Actors, such as the human player in Monopoly, generate UI events (such as clicking a button with a mouse to play a game or make a move). The UI software objects (such as a JFrame window and a JButton) must process the event and cause the game to play. When objects in the UI layer pick up an event, they must delegate the request to an object in the domain layer. What first object beyond the UI layer should receive the message from the UI layer? Name: Problem: Solution: Controller What first object beyond the UI layer receives and coordinates a System Operation? Assign the responsibility to an object representing one of these choices: +Represents the overall system a root object +Represents a use case scenario within which the system operation occurs. 12
:Monopoly Game
playGame
UI Layer
Domain Layer
13
High Cohesion
High Cohesion is an underlying Design Objective
Cohesion measures how functionally related the operations of a software element are. It also measures how much work an object is doing. Note low cohesion and bad coupling often go together. Name: Problem: Solution: High Cohesion How to keep objects focused, understandable, and manageable, and, as a side effect, support Low Coupling Assign responsibilities so that cohesion remains high. Use this criteria to evaluate alternatives.
14
:MonopolyGame
playGame doA doB
:??
:??
:??
doB doC
doC
Better Design
15
16
All the players (so that each can be used in taking a turn)
*LRG low representational gap. Lower the gap between our mental and software models.
17
playRound
18
The two Die objects (to roll them and calculate their total) All the squares the square organization (to be able to move to the correct new square)
19
Taking a Turn
Taking a turn means:
Calculating a random number between 2 and 12 Determining the location of the new square Moving the players piece from the old location to the new square. Calculating a new face value means changing information in Die, so by Expert, Die should be able to roll itself (generate a random number) and answer its face value. The new square location problem: Since the Board knows all its Squares, it should be responsible for finding a new square location, given an old square location and some offset (the dice total) The piece movement problem: By LRG it is reasonable for a Player to know its Piece, and a Piece its Square location (or even for a Player to directly know its Square location). By Expert, a Piece will set its new location, but may receive that new location from its Player. 20
players [i]:Player
:Player
takeTurn roll fv = getFaceValue
dice[i] : Die
:Board
:Piece
21
Visibility
Make a list of the messages (with parameters) and the classes of objects that send and receive them. Message playGame playRound takeTurn roll getFaceValue:int getLocation:Square getSquare(Square, int):Square setLocation(Square) create Sender UIlevel MonopolyGame MonoplyGame Player Player Player Player Player Board Receiver MonopolyGame MonoplyGame Player Die Die Piece Board Piece Square
22
Visibility
From the previous Table we learn what classes must be visible to each other to implement the System Operation: playGame Sender MonopolyGame Player Player Player Board Piece Receiver Player Die Piece Board Square Square Visibility Type Attribute (fixed) Attribute (fixed) Attribute (fixed) Attribute (fixed) Attribute (fixed) Attribute (Transient)
Four kinds of visibilities for object B to send a message to object A: A is global to B A is a paramether to some operation of B A is part of B A is a locally object in some operation of B 23
24
public int getFaceValue( ) { return faceValue; } public void build( int i) { Square s = new Square(Square + i, i 1); } public class Board { private static final int SIZE = 40; private List squares = new ArrayList(SIZE); public Board ( ) { buildSquares( ); linkSquares( ); } public Square getStartSquare ( ) { return (Square) squares.get(0); } } } public void link (int i) { Square current = (Square) squares.get(i); Square next = (Square) squares.get((i+1)%SIZE)); current.setNextSquare(next); } public void linkSquares( ) for (int i = 0; i < SIZE ; i++) link (i);
25
26
27
Better
Worse
28
29
location
Square {abstract}
Player
landedOn {abstract}
PropertySquare
landedOn
GoSquare
landedOn
RegularSquare
IncomeTaxSquare
landedOn
landedOn
30
Applying Polymorphism
p:Player
takeTurn roll fv =getFaceValue :int
dice[i] : Die
:Board
loc:Square
By Expert
By Polymorphism
31
p:Player
By polymorphism
addCash(200)
By Expert
:IncomeTaxSquare
landedOn(p)
p:Player
By polymorphism
byExpert
Polymorphic method landedOn directed to the (abstract) base class (interface) and is implemented by each of the concrete subclasses. 32
Pure Fabrication
Name: Problem: Pure Fabrication What object should have responsibilitywhen you do not want to violate High Cohesion and Low Coupling, or other goals, but solutions offered by Expert (for example) are not appropriate? Sometimes assigning responsibilities only to domain layer software classes leads to problems like poor cohesion or coupling, or low reuse potential. Solution: Assign a highly cohesive set of responsibilities to an artificial or convenience class that does not represent a domain concept. Example: Rolling the dice in a Monopoly game Dice are used in many games and putting the rolling and summing responsibilities in Player makes it impossible to generalize this service. Also, it is not now possible to simply ask for the current dice total without rolling again. 33
Pure Fabrication
Use a Cup to hold the dice, roll them, and know their total. It can be reused in many different applications where dice are involved.
:Cup
:Board
loc:Square
34