1 / 28

Understanding Relationships Among Objects Through Object-Oriented Design Heuristics

Explore the significance of coupling and cohesion in object-oriented design, including practical examples, benefits of high cohesion, and the impact of low coupling on design clarity. This text covers coupling between classes, cohesion in class responsibilities, and the relationship dynamics in object-oriented systems.

jbaughman
Télécharger la présentation

Understanding Relationships Among Objects Through Object-Oriented Design Heuristics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Relationships amongst Objects By Rick Mercer with help from Object-Oriented Design Heuristics, Arthur Riel

  2. Outline • Coupling / Cohesion • The only possible relationships between objects • A few design heuristics • Consider role play in current project

  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 makePayment() 1: create() :POST p : Payment 2: addPayment(p) :Sale 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 considered • in isolation from other design guidelines • such as Expert and High Cohesion makePayment() 1: makePayment() :POST :Sale 1.1. create() :Payment

  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 publicclassStack<E> { publicbooleanisEmpty() {} publicvoidpush(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 parameters • publicclassJukeBoxAccountextends JFrame { • // Someone else asks this object if a song can be played by a user • publicbooleanmayQueueUp(Song song, JukeboxAccountuser) { • returnsong.canBePlayedToday() && • user.canSelect(song.getPlayTimeInSeconds()) • } • }

  15. An object relationship occurs when… 4) One object constructs another publicclassJukeBoxAccountextends JFrame { private class SelectListener implements ActionListener { publicvoid actionPerformed(ActionEventae ) { if (mayQueueUp(selectedSong, currentUser)) PlayListplayList = 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 Melon cost() Restaurant Patron cost() Steak Meal Pie cost() Melon cost() Restaurant Patron cost() cost() Steak Pie cost()

  18. Meal Wrapper Class • Encapsulation makes 4 messages look like one • Containment simplifies things • RestaurantPatron 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 manyinstance 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. Contained objects don’t talk to their containers • 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 • currentAccountshould not send messages to Jukebox • The JukeboxAccountCollection need not know it is contained in an instance of Jukeboxshould be standAlone • All contained objects are loosely coupled • Meaning they are not dependent on each other

  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 ATM displayPIN() HaveACard? getPIN() Display Card Reader Keypad

  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) Jukebox canBePlayedToday()? allowedToPlay()? selectSong currentUser

  25. Information Expert • 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

  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)

More Related