Title: Pure Fabrication P. 329
1Pure Fabrication P. 329
Ch 22 GRASP Patterns Pure Fabrication Protected
Variations (Law of Demeter)
Problem You have a responsibility to assign to
a class, but assigning it to a class in the
conceptual model causes low coupling and/or high
cohesion. Solution Fabricate a class - create a
class that is not found in your conceptual model,
one that does not necessarily have a business
meaning to the business person.
2Pure Fabrication
Example Suppose we need to save instances of
Sale in a relational database. To which class in
the model do you assign this responsibility?
Since Sale has the information to be saved, Sale
would be suggested by Information Expert. To
manage data going to and from a relational
database will require a large number of
operations insert, delete, update, select,
rollback, commit, buffer management,
3Pure Fabrication
The Expert pattern suggests that Sale is the
expert, and so should be the class to do this.
Theres a lot involved - save, retrieve, commit,
rollback - what about LineItems? When you save a
Sale do you save LineItems too? We would end up
adding a lot to Sale that has nothing to do with
Sale-ness Sale becomes less cohesive and more
highly coupled to more non-domain classes. Sale
will become much more complex, and not so focused.
4Pure Fabrication
Pure Fabrication suggests to create a new class
for these new responsibilities
PersistentStorage is a fabrication it is made up
from your imagination it cannot be found in the
Domain Model
PersistentStorage
insert() delete() update() ...
Sale remains well-designed - high cohesion, low
coupling PersistentStorage class is relatively
cohesive - sole purpose is to store/retrieve
objects to/from a relational database
5Pure Fabrication
Example see pages 73-76 of Patterns in Java,
Volume 2 Mark Grand John Wiley Sons Fig 4.13
shows a conceptual model Fig 4.14 shows an
initial assignment of responsibilities, where the
ServiceManager does scheduling and invoicing. Fig
4.15 shows the fabrication of a new class,
InvoiceGenerator, which results in higher
cohesion/less coupling.
6- System manages a field service organization
- Organization sends technicians who install and
repair equipment on service calls to other
organizations that use the equipment - Some service calls are paid by the organization
that uses the equipment equipment vendors pay
from some service calls others are paid for
jointly. - Service manager is given field service projects
for a user organization - Service manager is schedules service technicians
to perform the tasks - Service manager sends invoices for completed
tasks to the paying organizations
7Patterns in Java, Volume 2 Fig 4.14
Organizes-work-for
1
UserOrganization
1
0..
Install/repair-equipment
FieldServiceProject
1
0..
1..
1..
ServiceTask
1..
schedules
0..
getPayor()
schedules
1..
1..
compute-invoices-for
pays-for
1
1
1
invoices
PayingOrganization
ServiceManager
performs
1..
1
Note ServiceManager is highly coupled to other
classes
ServiceTechnician
schedules
1..
1..
8- Consider the tasks assigned to the
ServiceManager - scheduling tasks
- scheduling projects
- scheduling technicians
- generating invoices
These are central to the function of the service
manager
no reasonable class in the domain to assign this
to, so using Pure Fabrication, fabricate a new
class for this purpose
9Patterns in Java, Volume 2 Fig 4.15
Organizes-work-for
1
UserOrganization
1
0..
Install/repair-equipment
FieldServiceProject
1
0..
1..
1..
ServiceTask
1..
schedules
0..
getPayor()
schedules
1..
1..
compute-invoices-for
pays-for
1
Paying Organization
1
1
ServiceManager
1..
invoices
performs
1
Note Pure Fabrication preserves low coupling and
high cohesion
1..
ServiceTechnician
1..
schedules
10Object Design P. 331-2
Design of objects divided into two groups
- Behavioural decomposition
- Pure Fabrication can support this
- Classes are determined by behavioural grouping
- managing persistent storage
- generating invoices
- Representational decomposition
- Classes represent real things found in the
problem domain - clerks use registers to create
sales comprising line items - Reduces the representational gap
- Objects do things that, in the real-world, are
done to them.
11Protected Variations P. 334
Problem How do we design systems so that changes
in its elements do not have an unfavourable
impact on other elements? Solution Identify
points of predicted variation/instability and
assign responsibilities to create a stable
interface around them Example Law of Demeter
(LoD) Special case of this pattern. (p. 336 ) If
objects traverse long object structure paths and
send messages to distant, indirect (stranger)
objects, the system is fragile with respect to
changes in the object structures - a common point
of instability in systems. LoD helps us avoid
creating such designs
12Law of Demeter
- Also called Dont Talk to Strangers
- Each class should only use a limited set of other
classes only units closely related to the
current unit. - Each class should only talk (send messages) to
its friends. Dont talk to strangers.
13Law of Demeter
- Dont Talk to Strangers places constraints on
what objects you should send messages to within a
method. Within a method, messages should only be
sent to the following objects - the this object (or self)
- a parameter of the method
- an attribute of this
- an element of a collection which is an attribute
of this - an object created within the method
14Law of Demeter
FRIENDS
15Dont Talk to Strangers
Suppose Register needs to find out the amount of
the payment
Payment
Register
Sale
getTenderedAmount()
paymentAmount() endSale() enterItem() makePayment(
) ...
becomeComplete() makeLineItem() makePayment() getT
otal() getPayment ...
add a method to get a payment
- The class diagram shows that
- Register knows about Sale, and
- Sale knows about Payments that have been made
towards it
16Dont Talk to Strangers
Assume Register has a paymentAmount method which
returns the current amount tendered for the
payment Sale has a method, getPayment, which
returns the Payment instance associated with the
Sale Consider In order to return the payment
amount, we could have a paymentAmount method in
Register such as public void paymentAmount() Pa
yment payment sale.getPayment() Money amount
payment. getTenderedAmount()
A little different from the texts example
17Dont Talk to Strangers
The previous has messages
Register
Sale
getPayment()
Register will have a dependency on Payment This
increases the coupling in our system
Payment
getTenderedAmount()
18Dont Talk to Strangers
- If getPayment() in Sale would invoke
getTenderedAmount() in Payment, and return the
payment amount, then we can de-couple Register
from Payment - make the solution more robust, less sensitive to
changes, less coupling
getPayment()
Register
Sale
Register will get the payment amount it is after,
but it wont know how it was obtained - see
Parnas concept of information hiding on page 339
getTenderedAmount()
Objects are only sending messages to their friends
Payment
19- Law of Demeter presentation
- www.ccs.neu.edu/research/demeter/talks/frameworks/
ubs/LoD.ppt - Karl J. Lieberherr Northeastern University
- other resources
- www.ccs.neu.edu/research/demeter/
- www.ccs.neu.edu/home/lieber/LoD.html
- Article on Information hiding
- www.computer.org/certification/beta/McConnell_Miss
ing.html
20Example Applying LoD as system changes
busStops
BusRoute
BusStopList
buses
0..
BusStop
BusList
waiting
0..
passengers
Bus
PersonList
Person
0..
21Find all persons waiting at any bus stop on a bus
route Collaborating classes
busStops
BusRoute
BusStopList
buses
0..
BusStop
BusList
waiting
0..
passengers
Bus
PersonList
Person
0..
22Applying Law of Demeter - Partial Java Solution
class BusRoute BusStopList busstops
void printWaitingPassengers () busstops-gtprintW
aitingPassengers () class BusStopList
BusStop stops void printWaitingPassengers
() for (int i 0 i lt stops.length i)
stopsi.printWaitingPassengers ()
23Applying Law of Demeter - Partial Java Solution
class BusStop PersonList waiting void
printWaitingPassengers () waiting.print ()
class PersonList Person people
void print () for (int i 0 i lt
people.length i) peoplei.print () class
Person String name void print ()
System.stdout.println (name)
24Suppose the class model is modified to
incorporate Villages.
What software changes are needed and still adhere
to LoD?
villages
BusRoute
BusStopList
buses
VillageList
busStops
0..
0..
BusStop
BusList
Village
waiting
0..
passengers
Bus
PersonList
Person
0..