1
Design by Responsibility(Craig Larman)
Design by Responsibility(Craig Larman)
Software Engineering
2
Object DesignObject Design
The rough steps followed so far include:Define requirements and model with use cases
Create domain model (conceptual class diag.)
Now to design objects we need to:Add methods to the classes and define messaging
between objects to fulfill the requirements
But that last step isn’t trivial!
The rough steps followed so far include:Define requirements and model with use cases
Create domain model (conceptual class diag.)
Now to design objects we need to:Add methods to the classes and define messaging
between objects to fulfill the requirements
But that last step isn’t trivial!
3
GRASP PatternsGRASP Patterns
GRASP patterns help define normal ways that objects interact with each otherGRASP is Larman’s term; “General Responsibility
Assignment Software Patterns”
We’ll cover five of the patterns in the text
For all 23 standard patterns, see Erich Gamma’s classic Design Patterns (ISBN 0201633612 or 0201634988)
GRASP patterns help define normal ways that objects interact with each otherGRASP is Larman’s term; “General Responsibility
Assignment Software Patterns”
We’ll cover five of the patterns in the text
For all 23 standard patterns, see Erich Gamma’s classic Design Patterns (ISBN 0201633612 or 0201634988)
4
ResponsibilitiesResponsibilities
The responsibilities for an object describe what behavior it needs to fulfill
DoingCreate an object
Perform a calculation
Start action in another object
Control activities in other objects
“Sale is responsible for creating SalesLineItem”
The responsibilities for an object describe what behavior it needs to fulfill
DoingCreate an object
Perform a calculation
Start action in another object
Control activities in other objects
“Sale is responsible for creating SalesLineItem”
5
ResponsibilitiesResponsibilities
KnowingAbout private encapsulated dataAbout related objectsAbout things it can calculate or derive“Sale is responsible for knowing its total”Most ‘knowing’ responsibilities are apparent
from the attributes and associations of the object
KnowingAbout private encapsulated dataAbout related objectsAbout things it can calculate or derive“Sale is responsible for knowing its total”Most ‘knowing’ responsibilities are apparent
from the attributes and associations of the object
6
ResponsibilitiesResponsibilities
Translating responsibilities into classes and methods depends on how detailed or general the responsibilities are
Methods are often implemented to fulfill responsibilities
Translating responsibilities into classes and methods depends on how detailed or general the responsibilities are
Methods are often implemented to fulfill responsibilities
7
Getters and SettersGetters and Setters
Detailed object methods often include a lot of getters and settersGetters ‘get’ some value for the outside
world, e.g. getTotal (a ‘knowing’ responsibility)
Setters ‘set’ some value – like assignment statements, e.g. setSecurityLevel (a ‘doing’ responsibility)
Detailed object methods often include a lot of getters and settersGetters ‘get’ some value for the outside
world, e.g. getTotal (a ‘knowing’ responsibility)
Setters ‘set’ some value – like assignment statements, e.g. setSecurityLevel (a ‘doing’ responsibility)
8
Responsibilities, Methods relatedResponsibilities, Methods related
:Sale
:Payment
makePayment()
create()
From Fig. 16.1, p. 217
makePayment implies Sale objects are responsible for creating Payments
Note Payment shifted down to show its creation
9
Defining PatternsDefining Patterns
Patterns capture well established “best practices” for design
Some are very low level; others are architectural
Each Pattern is defined by its Name, a summary of the Pattern’s Solution, and a description of the Problem it solves
Patterns capture well established “best practices” for design
Some are very low level; others are architectural
Each Pattern is defined by its Name, a summary of the Pattern’s Solution, and a description of the Problem it solves
10
Defining PatternsDefining Patterns
Patterns are not always the best solution
Good pattern descriptions include when the pattern may not apply, or the pros and cons of the pattern
Patterns are not always the best solution
Good pattern descriptions include when the pattern may not apply, or the pros and cons of the pattern
11
The First Five GRASP PatternsThe First Five GRASP PatternsInformation Expert
Creator
High Cohesion
Low Coupling
Controller
Information Expert
Creator
High Cohesion
Low Coupling
Controller
12
Information ExpertInformation Expert
Problem: what is the general principle of assigning responsibilities to objects?
Solution: assign responsibility to the Information Expert – the class which has the information needed to fulfill the responsibilityor Whoever has the data is responsible for managing and sharing it!
Problem: what is the general principle of assigning responsibilities to objects?
Solution: assign responsibility to the Information Expert – the class which has the information needed to fulfill the responsibilityor Whoever has the data is responsible for managing and sharing it!
13
Information ExpertInformation Expert
The domain model should inspire expansion into design classes which will handle all of the data and use it to meet requirements
A key step is that we have to make up the classes we think we’ll need, based on the system characteristics, and see if they can work correctly
The domain model should inspire expansion into design classes which will handle all of the data and use it to meet requirements
A key step is that we have to make up the classes we think we’ll need, based on the system characteristics, and see if they can work correctly
14
Information ExpertInformation Expert
So if we have a class called Sale (like Shipment in the homework assignments), one responsibility might be to provide the total cost of the Sale
We know from a typical invoice that a Sale might consists of a bunch of line items, so we might call their class SalesLineItem
So if we have a class called Sale (like Shipment in the homework assignments), one responsibility might be to provide the total cost of the Sale
We know from a typical invoice that a Sale might consists of a bunch of line items, so we might call their class SalesLineItem
15
Information ExpertInformation Expert
Each SalesLineItem may have a quantity
And each SalesLineItem needs someplace safe to store its description and price, so we’ll put that in a ProductSpecification
After defining the associations and multiplicity, we get Figure 16.3 (p. 222), shown on the next slide
Each SalesLineItem may have a quantity
And each SalesLineItem needs someplace safe to store its description and price, so we’ll put that in a ProductSpecification
After defining the associations and multiplicity, we get Figure 16.3 (p. 222), shown on the next slide
16
Information ExpertInformation Expert
-date-time
Sale
-description-price-itemID
ProductSpecification
-quantity
SalesLineItem
1
1..*
Contains
* 1
Described-by
17
Information ExpertInformation ExpertSo at the highest level, we need to get the
total cost from Sale
But in order to get that, we need the subtotal of each line item – so get that from the information expert for each line item
So at the highest level, we need to get the total cost from Sale
But in order to get that, we need the subtotal of each line item – so get that from the information expert for each line item
:Sale
getTotal()
18
Information ExpertInformation Expert
So each SalesLineItem can get the subtotal of that line; and the Sale will get those subtotals
But each line item needs the price of each item; get from ProductDescription
So each SalesLineItem can get the subtotal of that line; and the Sale will get those subtotals
But each line item needs the price of each item; get from ProductDescription
:Sale
getTotal()
:SalesLineItem
getSubtotal()
19
Information ExpertInformation Expert
Omitting variable assignments we have:
Where each object is responsible for providing the data it owns
Omitting variable assignments we have:
Where each object is responsible for providing the data it owns
:Sale
getTotal()
:SalesLineItem
getSubtotal()
:ProductDescription
getPrice()
20
Information ExpertInformation Expert
The class diagram becomes:The class diagram becomes:
+getTotal()
-date-time
Sale
+getPrice()
-description-price-itemID
ProductSpecification
+getSubtotal()
-quantity
SalesLineItem
1
1..*
Contains
* 1
Described-by
21
Information ExpertInformation Expert
Information Expert is used very frequently in object design
May not be suitable when coupling or cohesion dictate otherwise (see later)
Information Expert is used very frequently in object design
May not be suitable when coupling or cohesion dictate otherwise (see later)
22
CreatorCreator
Problem: Who is responsible for creating a new instance of a class?
Solution: Let B create instances of A if:B aggregates (is made up of) A
B contains (holds) A objects
B records instance of A objects
B closely uses A objects
B has data needed when A is created
Problem: Who is responsible for creating a new instance of a class?
Solution: Let B create instances of A if:B aggregates (is made up of) A
B contains (holds) A objects
B records instance of A objects
B closely uses A objects
B has data needed when A is created
23
CreatorCreator
Creation of objects is also a very common activity
In the previous example, Sale aggregates (contains) many SalesLineItem objects (one object per line in the Sale), hence is makes sense for Sale to be a Creator of SalesLineItem instances
Creation of objects is also a very common activity
In the previous example, Sale aggregates (contains) many SalesLineItem objects (one object per line in the Sale), hence is makes sense for Sale to be a Creator of SalesLineItem instances
24
CreatorCreator
Hence a responsibility of the system is that a Sale needs a method to makeLineItem
If you want add X (quantity) widgets to a shopping cart, then Sale adds them to
the cart
Hence a responsibility of the system is that a Sale needs a method to makeLineItem
If you want add X (quantity) widgets to a shopping cart, then Sale adds them to
the cart
25
CreatorCreator
The sequence diagram would be:The sequence diagram would be:
:Register :Sale
:SalesLineItem
makeLineItem()
create()
Fig. 16.8, p. 227
26
CreatorCreator
If the creation of an object is very complex, then the Factory pattern would be better (see Ch. 23)
If the creation of an object is very complex, then the Factory pattern would be better (see Ch. 23)
27
Best practice -create loosely coupled
components
Best practice -create loosely coupled
components High Level Modules should not depend upon
low
level modules and vice-versa. Both should
depend on abstractions.
Abstractions should not depend on details.
Details must depend on abstractions.
High Level Modules should not depend upon low
level modules and vice-versa. Both should
depend on abstractions.
Abstractions should not depend on details.
Details must depend on abstractions.
28
GOF Solution – Factory PatternGOF Solution – Factory Pattern
Use a Factory class to instantiate the component you need
Only the Factory knows about the concrete class, not your application
Use a Factory class to instantiate the component you need
Only the Factory knows about the concrete class, not your application
29
GOF Solution – Factory PatternGOF Solution – Factory Pattern
Pros – Helps to resolve tight coupling Cons – Intrusive: Components need to be requested
explicitly Need recompiling to change specific component inapplication
Pros – Helps to resolve tight coupling Cons – Intrusive: Components need to be requested
explicitly Need recompiling to change specific component inapplication
30
Alternative -Hollywood PrincipalAlternative -Hollywood Principal
aka “don’t call us, we’ll call you”
– Components should not be explicitly requested
– Components will be provided as needed
aka Inversion of Control
aka “don’t call us, we’ll call you”
– Components should not be explicitly requested
– Components will be provided as needed
aka Inversion of Control
31
Dependency InjectionDependency Injection
When IoC is about looking up plugin
implementation, Martin Fowler calls it
Dependency injection
Dependency injection is a term used to
resolve component dependencies by
injecting an instantiated component to satisfy
a dependency
When IoC is about looking up plugin
implementation, Martin Fowler calls it
Dependency injection
Dependency injection is a term used to
resolve component dependencies by
injecting an instantiated component to satisfy
a dependency
32
Inversion of Control/Dependency InjectionBeans do not depend on frameworkContainer injects the dependencies
Spring lightweight containerConfigure and manage beans
Inversion of Control/Dependency InjectionBeans do not depend on frameworkContainer injects the dependencies
Spring lightweight containerConfigure and manage beans
IoC/Dependency InjectionIoC/Dependency Injection
33
Dependency injectionBeans define their dependencies through constructor arguments or
propertiesThe container provides the injection at runtime
“Don’t talk to strangers”Also known as the Hollywood principle – “don’t call me I will
call you”Decouples object creators and locators from application logicEasy to maintain and reuseTesting is easier
Dependency injectionBeans define their dependencies through constructor arguments or
propertiesThe container provides the injection at runtime
“Don’t talk to strangers”Also known as the Hollywood principle – “don’t call me I will
call you”Decouples object creators and locators from application logicEasy to maintain and reuseTesting is easier
Inversion of ControlInversion of Control
35
Inversion of ControlInversion of Control青梅竹马
public class Girl { void kiss(){ Boy boy = new Boy(); }}
36
Inversion of ControlInversion of Control亲友介绍
public class Girl { void kiss(){ Boy boy = BoyFactory.createBoy(); }}
37
Inversion of ControlInversion of Control父母包办
public class Girl { void kiss(Boy boy){ // kiss boy boy.kiss(); }}
39
Inversion of Control (Type 0)Inversion of Control (Type 0)public class Girl implements Servicable {
private Kissable kissable;
public Girl() {
kissable = new Boy();
}
public void kissYourKissable() {
kissable.kiss();
}
}
40
Inversion of Control (Type 1)Inversion of Control (Type 1)
public class Girl implements Servicable {
Kissable kissable;
public void service(ServiceManager mgr) {
kissable = (Kissable) mgr.lookup(“kissable”);
}
public void kissYourKissable() {
kissable.kiss();
}
}
<container> <component name=“kissable“ class=“Boy"> <configuration> … </configuration> </component>
<component name=“girl" class=“Girl" /></container>
41
Inversion of Control (Type 2)Inversion of Control (Type 2)public class Girl {
private Kissable kissable;
public void setKissable(Kissable kissable) {
this.kissable = kissable;
}
public void kissYourKissable() {
kissable.kiss();
}
}
<beans> <bean id=“boy" class=“Boy"/> <bean id=“girl“ class=“Girl"> <property name=“kissable"> <ref bean=“boy"/> </property> </bean></beans>
42
Inversion of Control (Type 3)Inversion of Control (Type 3)public class Girl {
private Kissable kissable;
public Girl(Kissable kissable) {
this.kissable = kissable;
}
public void kissYourKissable() {
kissable.kiss();
}
}
PicoContainer container = new DefaultPicoContainer();container.registerComponentImplementation(Boy.class);container.registerComponentImplementation(Girl.class);Girl girl = (Girl) container.getComponentInstance(Girl.class);girl.kissYourKissable();
43
Low CouplingLow Coupling
Problem: How can we support low dependency among classes, low impact of changes, and increase reuse of classes?
Solution: Assign responsibilities so that coupling remains low
Coupling describes the extent of interconnection among classes
Problem: How can we support low dependency among classes, low impact of changes, and increase reuse of classes?
Solution: Assign responsibilities so that coupling remains low
Coupling describes the extent of interconnection among classes
44
Low CouplingLow Coupling
Notice that some coupling is needed – otherwise the classes don’t interact
Too much coupling means that changes to one class might have unexpected changes elsewhere
Related to “visibility” – how many other objects does each one need to see?
Notice that some coupling is needed – otherwise the classes don’t interact
Too much coupling means that changes to one class might have unexpected changes elsewhere
Related to “visibility” – how many other objects does each one need to see?
45
“ Stair” Object Structure“ Stair” Object StructureObject1 Object2 Object3 Object4 Object5
Message1()
Message2()
Message3()
Message4()
Message5()
Message6()
Message7()
Message8()
Low coupling (decentralized)Each object sees two other objects at most
46
“ Fork” Object Structure“ Fork” Object StructureObject1 Object2 Object3 Object4 Object5
Message1()
Message2()
Message3()
Message4()
Message5()
Message6()
Message7()
Message8()
High coupling (centralized)Object1 must see all other objects
47
Low CouplingLow Coupling
The Stair structure is generally preferred where possible
Might have to use Fork structure ifThe sequence of operations may change, and/or
New operations may be needed frequently
Subclasses are, by definition, high levels of coupling between objects
The Stair structure is generally preferred where possible
Might have to use Fork structure ifThe sequence of operations may change, and/or
New operations may be needed frequently
Subclasses are, by definition, high levels of coupling between objects
48
Low CouplingLow Coupling
Particularly avoid high coupling for objects which may change interface, implementation, or existence frequently
Desire for low coupling may conflict with Expert or High Cohesion patterns
No firm measure of what level of coupling is “good”
Particularly avoid high coupling for objects which may change interface, implementation, or existence frequently
Desire for low coupling may conflict with Expert or High Cohesion patterns
No firm measure of what level of coupling is “good”
49
High CohesionHigh Cohesion
Problem: how do you keep complexity manageable?
Solution: Assign responsibilities so that cohesion remains high
Cohesion is a measure of how closely related an object’s responsibilities are
High cohesion means a closely related set of narrowly defined responsibilities
Problem: how do you keep complexity manageable?
Solution: Assign responsibilities so that cohesion remains high
Cohesion is a measure of how closely related an object’s responsibilities are
High cohesion means a closely related set of narrowly defined responsibilities
50
High CohesionHigh Cohesion
In other words, don’t make an object do too much work!
Low cohesion generally results from remaining too abstract when defining responsibilities
Per Booch, high cohesion is when the elements of a class “all work together to produce some well-bounded behavior”
In other words, don’t make an object do too much work!
Low cohesion generally results from remaining too abstract when defining responsibilities
Per Booch, high cohesion is when the elements of a class “all work together to produce some well-bounded behavior”
51
High CohesionHigh Cohesion
An object which has a kitchen-sink function (it catches all the functions except the kitchen sink) generally has very low cohesion
A single complex function can result in low cohesion
Moderate cohesion would have similar, but not closely related, functions together
An object which has a kitchen-sink function (it catches all the functions except the kitchen sink) generally has very low cohesion
A single complex function can result in low cohesion
Moderate cohesion would have similar, but not closely related, functions together
52
High CohesionHigh Cohesion
High cohesion classes have some responsibilities in one set of functions, and use other objects to accomplish them
Modular design is a similar concept as ‘low coupling and high cohesion’
Conversely, high coupling and low cohesion often appear together
High cohesion classes have some responsibilities in one set of functions, and use other objects to accomplish them
Modular design is a similar concept as ‘low coupling and high cohesion’
Conversely, high coupling and low cohesion often appear together
53
High CohesionHigh Cohesion
Deliberately violating high cohesion is rare
Might have to do it:To isolate related functions (rare)
To distribute object to different servers
To manage an external interface
Deliberately violating high cohesion is rare
Might have to do it:To isolate related functions (rare)
To distribute object to different servers
To manage an external interface
54
ControllerController
Problem: who is responsible for handling external input system events?
Solution: assign the responsibility to a Controller objectFaçade controller represents the entire
subsystem or interfaceSession controller handles an entire use
case where some events may occur
Problem: who is responsible for handling external input system events?
Solution: assign the responsibility to a Controller objectFaçade controller represents the entire
subsystem or interfaceSession controller handles an entire use
case where some events may occur
55
ControllerController
An ‘input system event’ is some event from an external actor (human or not)
The Controller object is responsible for deciding what to do with the input system event
An ‘input system event’ is some event from an external actor (human or not)
The Controller object is responsible for deciding what to do with the input system event
56
ControllerController
So the Controller pattern applies to both management of external system interfaces (capture the entire interface in a single controller class), and managing inputs from user interfaces
User interface controllers generally end with <>Handler, <>Coordinator, or <>Session, where <> = <Use Case Name>
So the Controller pattern applies to both management of external system interfaces (capture the entire interface in a single controller class), and managing inputs from user interfaces
User interface controllers generally end with <>Handler, <>Coordinator, or <>Session, where <> = <Use Case Name>
57
ControllerController
Note that user interfaces (e.g. windows, views, or documents) are NOT part of the Controller’s job – those belong to an object at the Interface (or Presentation) Layer
Controller acts as a façade between interface and the application
Controllers DELEGATE work to other objects – they don’t do it themselves
Note that user interfaces (e.g. windows, views, or documents) are NOT part of the Controller’s job – those belong to an object at the Interface (or Presentation) Layer
Controller acts as a façade between interface and the application
Controllers DELEGATE work to other objects – they don’t do it themselves
58
BCE ObjectsBCE Objects
We can break objects into three major types for many purposesBoundary objects (user interface window, buttons,
etc.)
Control objects (controllers who make decisions, here also called ‘use case handlers’)
Entity objects (persistent objects which contain data)
We can break objects into three major types for many purposesBoundary objects (user interface window, buttons,
etc.)
Control objects (controllers who make decisions, here also called ‘use case handlers’)
Entity objects (persistent objects which contain data)
59
BCE ObjectsBCE Objects
These might be correlated to the kinds of computers involved in processing themUser interface might be at a PC level
(e.g. web browser)
Controller objects might run on an application server (captures logic, e.g. web server)
Entity objects might run on a database server (stores data)
These might be correlated to the kinds of computers involved in processing themUser interface might be at a PC level
(e.g. web browser)
Controller objects might run on an application server (captures logic, e.g. web server)
Entity objects might run on a database server (stores data)
60
Façade ControllerFaçade Controller
Façade controllers hide an entire system or subsystem under one class, such as Register or SystemAvoid except for simple external systems
Works well if only a few events to manage; otherwise may need use case controllers to break down system functions into smaller sets (p. 241)
Façade controllers hide an entire system or subsystem under one class, such as Register or SystemAvoid except for simple external systems
Works well if only a few events to manage; otherwise may need use case controllers to break down system functions into smaller sets (p. 241)
62
Avoiding Bloated ControllersAvoiding Bloated ControllersEven a façade controller should generally have
more than one class
Beware of controllers which perform work without calling another class
Controllers should have few or no attributes
Fix bloat by adding more controller classes, and/or redesign to delegate more work
Even a façade controller should generally have more than one class
Beware of controllers which perform work without calling another class
Controllers should have few or no attributes
Fix bloat by adding more controller classes, and/or redesign to delegate more work
63
Use Case RealizationUse Case Realization
Every scenario in a use case can become a ‘use case realization,’ which shows how the design model meets the requirements for that use case
Use Case Realization is UP term, not UML
Interaction diagrams help express Use Case Realization
Every scenario in a use case can become a ‘use case realization,’ which shows how the design model meets the requirements for that use case
Use Case Realization is UP term, not UML
Interaction diagrams help express Use Case Realization
64
Use Case RealizationUse Case Realization
Use case suggests system events shown in system sequence diagram
Effect of operations may be documented in operation contracts
Events represent messages which initiate interaction diagrams
Interaction diagrams describe communication between classes
Use case suggests system events shown in system sequence diagram
Effect of operations may be documented in operation contracts
Events represent messages which initiate interaction diagrams
Interaction diagrams describe communication between classes
65
Interaction DiagramsInteraction Diagrams
Recall the collaboration diagrams are specific to one use case
Sequence diagrams generally show one scenario for one use case; might show extensions
Operations contracts describe the conditions for one event in one use case
Recall the collaboration diagrams are specific to one use case
Sequence diagrams generally show one scenario for one use case; might show extensions
Operations contracts describe the conditions for one event in one use case
66
Models Don’t Start PerfectModels Don’t Start Perfect
Expect that early requirements, and the initial domain model (conceptual class diagram) will not be perfectBut that doesn’t mean do them poorly!
Maintain contact with customer and subject experts to keep improving models
Conceptual classes inspire design classesBut many additional classes likely needed
Expect that early requirements, and the initial domain model (conceptual class diagram) will not be perfectBut that doesn’t mean do them poorly!
Maintain contact with customer and subject experts to keep improving models
Conceptual classes inspire design classesBut many additional classes likely needed
67
Model-View SeparationModel-View Separation
Non-GUI objects should not be involved in output tasks
This reinforces the Boundary/Control/Entity object distinction earlier
Controllers should know the information to be displayed in output, but actual output is a boundary object’s purpose
Non-GUI objects should not be involved in output tasks
This reinforces the Boundary/Control/Entity object distinction earlier
Controllers should know the information to be displayed in output, but actual output is a boundary object’s purpose
68
More UML NotationMore UML NotationConstraints are tagged with curly brackets {}. An algorithm may be
shown if needed.
Notes are in text boxes which also have the upper right corner dog-eared
Constraints are tagged with curly brackets {}. An algorithm may be shown if needed.
Notes are in text boxes which also have the upper right corner dog-eared
This the the body of a Note box. It also has a Name, which isn't visible.
{s.isComplete = true} <- Constraint
<- Note
70
Iteration 2Iteration 2
The text’s second iteration assumes that in iteration 1 everything was done through development of the design class diagram, and major architecturally important parts of the system have been coded and tested
Iteration 2 is refining the design through additional patterns (which we aren’t covering)
The text’s second iteration assumes that in iteration 1 everything was done through development of the design class diagram, and major architecturally important parts of the system have been coded and tested
Iteration 2 is refining the design through additional patterns (which we aren’t covering)
71
Iteration 2Iteration 2
Iteration 2 also adds more scenarios to the foundation already established
Additional lower priority use cases may be fully defined
The system sequence diagram may be expanded to include external systems (p. 324)
Iteration 2 also adds more scenarios to the foundation already established
Additional lower priority use cases may be fully defined
The system sequence diagram may be expanded to include external systems (p. 324)