(first attempt). • Let each noun in the specification correspond to a class and each
verb to a method of a class. • Add concepts from the application domain ...
PowerPoint Slides Object-Oriented Design Using JAVA by Dale Skrien
Chapter 5
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Designing and building a software system from scratch • Develop a precise specification of the system • Determine the classes, their responsibilities and collaborators • Determine the precise protocol or interface of the classes • Implement the classes Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Use cases • A use case is a sequence of steps indicating how the program is to behave in a certain situation to achieve a particular goal. • Create a use case for each of the ways the system is expected to behave.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.1. A use case diagram for a word frequency counter application.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Finding the classes (first attempt) • Let each noun in the specification correspond to a class and each verb to a method of a class • Add concepts from the application domain Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
CRC cards • CRC stands for “Class, Responsibilities, and Collaborators” • Use one note card for each class • Use role playing to determine responsibilities and collaborators
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.2. A CRC card for a WordFrequencyAnalyzer class. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.3. A WordFrequencyCollection CRC card.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.4. A WordCounter CRC card. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Class Protocols public class WordCounter { public WordCounter(); //constructor public void checkFileExistence(String filename); public File createFile(); public WordFrequencyAnalyzer createAnalyzer(); public void initiateAnalysis(); public getAndPrintResult(); } Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Class Protocols public class WordFrequencyAnalyzer { public WordFrequencyAnalyzer(); //constructor public void analyzeText(File file); public WordFrequencyCollection getResults(); } public class WordFrequencyCollection { public WordFrequencyCollection(); //constructor public void editCollection(); public String toString(); } Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Class Protocols public class WordCounter { public static void main(String[] args); } public class WordFrequencyCollection { public WordFrequencyCollection(); //constructor public void add(String word); public String toString(); }
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Class Protocols public class WordFrequencyCollection implements Iterable { public WordFrequencyCollection(); //constructor public void add(String word); public Iterator iterator(); public int getFrequency(String word); }
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Class Protocols public class WordCounter { public static void main(String[] args) { //create the file File file = new File(args[0]); //test to see whether the file exists and can be read try { new FileReader(file); } catch (FileNotFoundException e) { System.out.println(“error: file cannot be read”); System.exit(0); } //analyze the file WordFrequencyAnalyzer analyzer = new WordFrequencyAnalyzer(); analyzer.analyzeText(file); //get and display the results WordFrequencyCollection collection = analyzer.getResults(); for(String word: collection) { System.out.println(word + “:” + collection.getFrequency(word) }; } } } Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.5. The word frequency analyzer classes.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline When working in the early high-level design phase, keep the discussion at a high level. In particular, avoid wasting time on implementation details and lowlevel data representations.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Maximize cohesion of classes • A class should model one concept • All its methods should be related to and appropriate for that concept • Promotes understanding and reusability of the class • Example: The Java String class
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Every class should be responsible for doing one thing only and doing it well.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.6. An ill-formed God class with all the responsibilities and slave (data-only) classes. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Separation of responsibilities Example: Traversing a Graph object. Who keeps track of which nodes of the Graph have already been visited? – The nodes themselves – The Graph object – A different object
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.7. A graph with 5 nodes and 5 edges.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Different kinds of responsibilities should be separated among different objects.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline (Expert pattern) • The object that contains the necessary data to perform a task should be the object that performs the task. • “Ask not what you can do to an object, ask what an object can do to itself.” • “What is it I’m doing with this data and why doesn’t the class do it for me?” Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Avoid duplication. This is also known as the DRY principle (“Don’t Repeat Yourself.”)
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
More about duplication • Duplication can occur in many forms: – duplicate copies of same data – duplicate code within a method or between methods – duplicate processes (duplicate execution of a piece of code)
• Code with duplication is less readable and less maintainable than code without duplication. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Only one class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Only one class should be responsible for knowing and maintaining a set of data, even if that data is used by many other classes. Corollary: Avoid duplicate copies of data.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Behavior of a class • Should a class have only the minimum necessary behavior to accomplish its tasks? • Should we add more behavior to increase the reusability of the class? • Should we add lots of auxiliary methods to make the class easier to use? • What should the protocol be for each method? Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Give classes complete and consistent interfaces.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Examples of completeness and consistency • GUI components could have setSelected() and setUnselected () methods, but better to have setSelected(boolean b) and isSelected() methods. • If there is a getXXX method, consider a setXXX method unless the XXX property is read only. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Mutability vs. Immutability • When should classes be made immutable? • General answer: Whenever possible • Advantages of immutable classes: – can easily share immutable objects – they have guaranteed behavior
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Implementing immutability • Make all instance variables private or final • Exclude any modifier methods • Prevent overriding by making the class final or making all the methods final.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Creating an immutable version of a mutable class • Consider the java.awt.Point class, which is mutable • How can you create a FixedPoint class that is identical to the Point class but is immutable?
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
3 ways to design a FixedPoint class • Design it independent of the java.awt.Point class • Make it a subclass of Point • Have it delegate to Point
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.8. FixedPoint class implemented as a subclass of java.awt.Point. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.9. FixedPoint class implemented using delegation to java.awt.Point. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Using Delegation public class FixedPoint //attempting immutability using delegation { private Point pt; public FixedPoint(Point p) //constructor { this.pt = p; } public FixedPoint(int x, int y) //constructor { this.pt = new Point(x,y); } public double getX() { return pt.getX(); } public double getY() { return pt.getY(); } public Point getLocation() { return pt; } }
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Problem with FixedPoint (1) FixedPoint fp = new FixedPoint(3,4); System.out.println(fp.getX()); //prints 3 Point loc = fp.getLocation(); loc.x = 5; System.out.println(fp.getX()); //prints 5
Fixed by implementing public Point getLocation() { return pt.getLocation(); } Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Problem with FixedPoint (2) Point p = new Point(3, 4); FixedPoint fp = new FixedPoint(p); System.out.println(fp.getX()); //prints 3 p.x = 5; System.out.println(fp.getX()); //prints 5
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Solution public final class FixedPoint //corrected version { private Point pt; public FixedPoint(Point p) { this.pt = new Point(p); } //copy constructor public FixedPoint(int x, int y) { this.pt = new Point(x, y); } public double getX() { return pt.getX(); } public double getY() { return pt.getY(); } public Point getLocation() { return pt.getLocation(); } }
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Designing for Change • Classes often need to have bugs fixed, be optimized, or have behavior added • Therefore design classes to make it easy to maintain, modify, and extend them. • “Change happens. Deal with it.”
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Design your classes and interfaces so that they can handle change.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Open-Closed Principle • Design your classes so that they are easy to extend if new behavior is needed, but design them in a way so that existing classes never need to be modified. • The benefit is that it allows you to avoid cascading chains of changes to existing classes, which can be time consuming and introduce new bugs • Particularly useful for software libraries Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Follow the Open-Closed Principle when designing software. That is, design software to be open for extension but closed for modification.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Coding to interfaces • One way to make code able to handle change is to code to interfaces instead of classes. • Example: If a variable v of type LinkedList uses only the iterator, add, and size methods of the LinkedList class, it would be better to declare v to be of type List and even better to declare v to be of type Collection. This allows many more types of values to be assigned to v without modifying any of the existing uses of v. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Code to interfaces, not classes. That is, wherever possible write your code so that objects are referred to by the interfaces they implement instead of by the concrete class to which they belong.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
More ways to design for change • Minimize coupling--reduce the number of dependencies of classes on each other • Use encapsulation--group related items and protect them from access by others. • Use information hiding--keep implementation details hidden
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Example • Suppose a Point class has a public nonfinal field x that is accessed by many other objects. • If you need to continually display the current value of x in a window, the window must repeatedly poll x, since its value can be changed in many places.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.10. The Window class may have no way of knowing the user changed the value of p.x since x is a public field. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Example (continued) • If the field x were private with getX and setX methods, then the system could be modified to avoid polling x. • The modification would consist of subclassing the Point class so that the setX method notifies the Window whenever it is called
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.11. By making x and y private in the Point class, we can ensure the Window is notified--the NotifierPoint notifies the Window of the change in x. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
ATM example • To get an account balance from the bank name b, branch number r, customer name c, and account number a, an ATM could execute Balance balance = centralControl! .getBank(b).getBranch(r).getCustomer(c)! .getAccount(a).getBalance();!
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.12. The UML sequence diagram for the first approach at getting the balance. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
ATM example (continued) • Alternatively, the ATM could issue Balance balance =! centralControl.getBalance(b,r,c,a);
• CentralControl could in turn find the bank and ask it for the balance, giving it r, c, and a • The bank in turn could find the branch and ask it for the balance, giving it c, and a • Similarly, the branch could find the customer and ask it for the account, etc. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Figure 5.13. The UML sequence diagram for the second approach at getting the balance. Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
ATM example (concluded) • Which approach is best? • The second approach better hides design and implementation details and reduces coupling. • There is “inappropriate intimacy” among the classes in the first approach.
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Law of Demeter Inside a method body, an object should send messages only to objects in the following categories: 1. this object itself 2. this object's instance variables 3. the method's parameters 4. any object the method creates 5. any object returned by a call to one of this object's methods 6. the objects in any collection that falls into these categories Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.
Guideline Obey the Law of Demeter. This principle can be summarized as “talk only to your immediate neighbors” or “don’t talk to strangers.”
Copyright © The McGraw-Hill Companies, Inc. Permission required for reproduction or display.