1 By Rick Mercer with help from Object-Oriented Design Heuristics, Arthur Riel Relationships amongst...
-
Upload
charles-sanders -
Category
Documents
-
view
222 -
download
4
Transcript of 1 By Rick Mercer with help from Object-Oriented Design Heuristics, Arthur Riel Relationships amongst...
1
By Rick Mercer with help from
Object-Oriented Design Heuristics, Arthur Riel
Relationships amongst Objects
2
• Coupling / Cohesion
• The only possible relationships between objects
• A few design heuristics
• Consider role play in current project
Outline
3
Coupling
Coupling: A measure of how strongly one class is connected to, has knowledge of, or relies upon other classes– Low coupling: the class is not dependent on many other
classes--good– High Coupling: class is dependent on many others--bad
•A change to one class forces changes in others•More difficult to understand a type in isolation•Harder to reuse because it depends on others
Assign responsibilities so coupling remains low
4
Which is the better design?
Should a Point of Sale Terminal (POST) object construct an instance of Payment, then add the payment to the sale – POST would be coupled to both Payment and Sale in the
following Collaboration diagram a UML diagram that will not be on test
• With this design, POST needs to know 2 classes
:POST p : Payment
:Sale
makePayment() 1: create()
2: addPayment(p)
Example from Craig Larmans Applying UML and Patterns
5
An alternative design
Try associating Payment with Sale– Sale is coupled to Payment in either design
– But low coupling favors this 2nd design
In practice coupling can’t be consideredin isolation from other design guidelinessuch as Expert and High Cohesion
:POST :Sale
:Payment
makePayment() 1: makePayment()
1.1. create()
6
Try to keep coupling low
Common forms of coupling– Class A has an instance of Class B– Class A send a message to an instance of Class B– Class A is a subclass of Class B (inheritance)– Class A implements interface I
Coupling does occur, in any design A dangerous case of high coupling:
– Allow Class A to use instance variable of Class B
– Low coupling is a sign of good design
7
High Cohesion, Good
Cohesion – Synonyms: consistency, pulling together– A measure of how strongly related and focused the
responsibilities of a class are Assign responsibilities for high cohesion
– High cohesion is good– Low cohesion is bad
• hard to understand• hard to reuse• hard to maintain• fragile; constantly affected by change
8
High Cohesion
High cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module Examples
PlayList manages the songs in the queue BankAccount has no queueUpSong method Any well structured class where the methods are
related, String for example
9
High vs. Low Cohesion
High functional cohesion exists when the elements of a class "all work together to provide some well-bounded behavior" Grady Booch
Low cohesion– One class is responsible for things in different functional
areas. Examples: – Model arranges Views, Listeners make the Rules
– One class has sole responsibility of many tasks• Jukebox coordinate activities and determines if a song
can play, plays audio files, maintains collections, manages the play list, ...
10
High Cohesion
A class has moderate responsibilities in one functional area and collaborates with other objects to fulfill tasks:– e.g. PokerDealer coordinates but gets help from
• a deck of cards that can shuffle and deal cards
• the player that can figure out what to do next and knows what he or she can bet
• a view to show poker hands, pot, cards, animations
Small number of methods, highly related functionality, doesn't do too much
11
Benefits of High Cohesion
Design is clearer and more easily understood Maintenance (bug fixes, enhancements, changing
business rules) is easier– The fewer classes you touch the better Adele Goldberg
High cohesion can help you attain lower coupling
12
Relationship Between Objects
1) Object relationships occur when one object sends a message to itself
public class Stack<E> {
public boolean isEmpty() {}
public void push(E element) { if(this.isEmpty()) first = new Node(element, first); else … }
13
An object relationship occurs when…
2) An object sends a message to an instance variable
private JTextArea textEditor = new JTextArea("You can edit me");
public FirstGUI() { this.setSize(500, 400); textEditor.setLineWrap(true); textEditor.setWrapStyleWord(true); textEditor.setBackground(Color.RED); textEditor.setFont(new Font("Courier", Font.BOLD, 12));
14
An object relationship occurs when…
3) One object sends messages to other objects passed as formal parameterspublic class JukeBoxAccount extends JFrame { // Someone else asks this object if a song can be played by a user public boolean mayQueueUp(Song song, JukeboxAccount user) { return song.canBePlayedToday() && user.canSelect(song.getPlayTimeInSeconds()) }}
15
An object relationship occurs when…
4) One object constructs anotherpublic class JukeBoxAccount extends JFrame {
private class SelectListener implements ActionListener { public void actionPerformed(ActionEvent ae ) { if (mayQueueUp(selectedSong, currentUser)) PlayList playList = new PlayList(song); // Not a good idea else … } }}
16
Design Guideline
Minimize the number of objects with which another object collaborates
Worst case: The design has a collection of simple
objects where each one uses all others
One class could contain several smaller objects
17
A Meal Class Wrap 3 Smaller Classes
Meloncost()
RestaurantPatron
Steakcost()
Meloncost()
Piecost()
RestaurantPatron
Steakcost()
Piecost()
cost()
Meal
18
Meal Wrapper Class
Encapsulation makes 4 messages look like oneContainment simplifies thingsRestaurantPatron collaborates with one object
now, instead of three
19
If you have instance variables, use them
Containment implies a relationship, messages should be sent to contained objects
If no messages are sent to a contained object, it doesn't belong, Put the attribute in the right class
An exception: Container classes– ArrayList, HashMap, TreeMap, and so on, do not send
messages to their elements• Okay, equals or compareTo sometimes
• The collection’s responsibility is to add, find, and remove elements
20
Don't use too many instance variables
Most of the methods in a class should be using most of the instance variables most of the time
If not, perhaps there should be two classes
Classes should not contain more instance variables than a developer can fit in short term memory
Maximum should be 7 plus or minus 2 That's about 5 to 9 instance variables
21
A class must know what it contains, but the contained class should not know who contains it– It's okay for a bedroom to know it has a clock, but
the clock should not be dependent on the bedroom– currentAccount should not send messages to Jukebox
– The JukeboxAccountCollection need not know it is contained in an instance of Jukebox should be standAlone•All contained objects are loosely coupled
– Meaning they are not dependent on each other
Contained objects don’t talk to their containers
22
Use a Mediator to Coordinate Activities
Objects that share lexical scope -- those in the same containment --need not have relationships between them
Consider an ATM that contains a card reader and a display screen– The card reader should not send a message to
the display screen• better reuse--could use the card reader software for a
security entrance without taking the display screen
23
Violation Increases Complexity
An ATM may contain – card reader, display screen, and keypad– The ATM should coordinate activities between these
three objects• Avoid collaborations between instance variables if possible
HaveACard?
Card Reader
displayPIN()
getPIN()
Display Keypad
ATM
24
In our system?
The Jukebox may contain – currentUser– selectedSong– But they need not send messages to each other\
– but they could currentUser.canPlay(selectedSong)
allowedToPlay()?
currentUser
canBePlayedToday()?
selectSong
Jukebox
25
The most basic, general principle of assigning responsibilities (behavior/methods) is to – Assign the responsibility to the object that has the
information necessary to fulfill it.
– “That which has the information, does the work.”
– Who decides if the jukebox object can select?
Most important skill in OO Design– Which objects should do what?• find the objects• assign responsibilities to the correct objects
Information Expert
26
Role Play
Jukebox: Now I need to determine whether or not the current user can play the selected Song. Who is responsible for knowing the playing time of any Song?
Song: It seems like I should be responsible for knowing the duration of my Song. For example, it might take 3 minutes and 34 seconds to be completely played. I'll add the responsibility “know play time”.
Jukebox: Okay, now I should check to make sure the user is able to select this Song before telling playlist to queue it up. I seem to remember I cannot simply play a Song without checking on a few things. I know the current user and the selected Song. What do I do now?
27
Alternative #1
JukeBox: So tell me Song, how many minutes and seconds do you require to be played?
Song: 3 minutes and 34 seconds.
JukeBox: JukeboxAccount, do you have 3 minutes and 34 seconds credit?
JukeboxAccount: I'll be responsible for maintaining remaining time credit, so I can answer that, Yes, I have enough credit.
JukeBox: JukeboxAccount, have you played fewer than 2 Songs?
JukeboxAccount : I have not played 2 songs today.
JukeBox: Okay, now we can play the Song. Here it playList.
PlayList: Okay JukeBox, I will add this Song to my queue. I'll take care of the add(String fileName) responsibility
28
Alternative #2
JukeBox: JukeboxAccount, can you play this Song?
JukeBoxAccount: It feels as though I should be responsible for maintaining my own time credit, it seems appropriate that I should also know how many Songs I've played today. So I should be able to do some simple calculations to give you the answer you seek. Yes JukeBox, I can play the Song you sent me. I'll add these responsibilities to my CRC card:
• know how much time credit I have left
• know how many Songs I've played on this date
• respond to a message like this: JukeboxAccount.canSelect(selectedSong)