17-Oct-15 Design Patterns and Refactoring CSC 2053.

Slides:



Advertisements
Similar presentations
More on Classes Inheritance and Polymorphism
Advertisements

OO Programming in Java Objectives for today: Overriding the toString() method Polymorphism & Dynamic Binding Interfaces Packages and Class Path.
© 2010 Shawn A. Bohner Software Construction and Evolution - CSSE 375 Even more Bad Smells in Code Shawn & Steve Q1 Shawn & Steve Hint 
Software Evolution and Refactoring July Introduction Any changes on software by developers or users These changes are costly How we can design.
CS 211 Inheritance AAA.
Inheritance Inheritance Reserved word protected Reserved word super
1 Software Maintenance and Evolution CSSE 575: Session 1, Part 4 Even more Bad Smells in Code Steve Chenoweth Office Phone: (812) Cell: (937)
Chapter 6: Using Design Patterns
Inheritance. Extending Classes It’s possible to create a class by using another as a starting point  i.e. Start with the original class then add methods,
Aalborg Media Lab 23-Jun-15 Inheritance Lecture 10 Chapter 8.
12-Jul-15 Refactoring. 2 Refactoring is: restructuring (rearranging) code......in a series of small, semantics-preserving transformations (i.e. the code.
13-Jul-15 Refactoring II. Books Design Patterns is the classic book by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides Basically a catalog.
Refactoring to Patterns Ravindra Chilaka Extreme Programming Seminar XP 2004 b.
1 Chapter 8 Objects and Classes. 2 Motivations After learning the preceding chapters, you are capable of solving many programming problems using selections,
(c) University of Washington03-1 CSC 143 Java Inheritance Reading: Ch. 10.
15-Aug-15 Design Patterns and Refactoring. 2 History A Pattern Language: Towns, Buildings, Construction, Christopher Alexander, 1977 The Timeless Way.
21-Aug-15 Design Patterns and Refactoring. 2 History A Pattern Language: Towns, Buildings, Construction, Christopher Alexander, 1977 The Timeless Way.
1 Some Patterns of Novice Programs Author : Eugene Wallingford ; Dan Steinberg ; Robert Duvall ; Ralph Johnson Source : PLoP 2004 Advisor : Ku-Yaw Chang.
REFACTORING Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
Chapter 3 Introduction to Collections – Stacks Modified
Polymorphism, Inheritance Pt. 1 COMP 401, Fall 2014 Lecture 7 9/9/2014.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
Object-Oriented Software Engineering Practical Software Development using UML and Java Chapter 6: Using Design Patterns 1.
Method Overriding Remember inheritance: when a child class inherits methods, variables, etc from a parent class. Example: public class Dictionary extends.
CSE 501N Fall ‘09 14: Inheritance 20 October 2009 Nick Leidenfrost.
Refactoring Improving the structure of existing code Refactoring1.
17-Oct-15 Refactoring. 2 Refactoring is: restructuring (rearranging) code......in a series of small, semantics-preserving transformations (i.e. the code.
Chapter 2 Introducing Interfaces Summary prepared by Kirk Scott.
RIT Computer Science Dept. Goals l Inheritance l Modifiers: private, public, protected l Polymorphism.
Refactoring1 Improving the structure of existing code.
Object-Oriented Software Engineering Practical Software Development using UML and Java Chapter 6: Using Design Patterns.
31-Oct-15 Simple UML IB Computer Science. 2 What is UML? UML stands for Unified Modeling Language UML is a diagramming language designed for Object- Oriented.
Refactoring Deciding what to make a superclass or interface is difficult. Some of these refactorings are helpful. Some research items include Inheritance.
Design Patterns Gang Qian Department of Computer Science University of Central Oklahoma.
Objects & Dynamic Dispatch CSE 413 Autumn Plan We’ve learned a great deal about functional and object-oriented programming Now,  Look at semantics.
Chapter 3 Inheritance and Polymorphism Goals: 1.Superclasses and subclasses 2.Inheritance Hierarchy 3.Polymorphism 4.Type Compatibility 5.Abstract Classes.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Java Software Solutions Foundations of Program Design Sixth Edition by Lewis.
Inheritance. Inheritance is a fundamental object-oriented design technique used to create and organize reusable classes Chapter 8 focuses on: deriving.
M1G Introduction to Programming 2 5. Completing the program.
CPS Inheritance and the Yahtzee program l In version of Yahtzee given previously, scorecard.h held information about every score-card entry, e.g.,
Object-Oriented Software Engineering Practical Software Development using UML and Java Chapter 6: Using Design Patterns.
Design Patterns Software Engineering CS 561. Last Time Introduced design patterns Abstraction-Occurrence General Hierarchy Player-Role.
Liang, Introduction to Java Programming, Sixth Edition, (c) 2007 Pearson Education, Inc. All rights reserved Chapter 11 Object-Oriented.
Inheritance CSI 1101 Nour El Kadri. OOP  We have seen that object-oriented programming (OOP) helps organizing and maintaining large software systems.
M1G Introduction to Programming 2 3. Creating Classes: Room and Item.
Coming up: Inheritance
1 Inheritance Reserved word protected Reserved word super Overriding methods Class Hierarchies Reading for this lecture: L&L 9.1 – 9.4.
CS 325: Software Engineering March 19, 2015 Applying Patterns (Part B) Code Smells The Decorator Pattern The Observer Pattern The Template Method Pattern.
Refactoring1 Improving the structure of existing code.
Chapter 11: Advanced Inheritance Concepts. Objectives Create and use abstract classes Use dynamic method binding Create arrays of subclass objects Use.
CS2102: Lecture on Abstract Classes and Inheritance Kathi Fisler.
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
Session 7 Introduction to Inheritance. Accumulator Example a simple calculator app classes needed: –AdderApp - contains main –AddingFrame - GUI –CloseableFrame.
Subclassing, pt. 2 Method overriding, virtual methods, abstract classes/methods COMP 401, Fall 2014 Lecture 9 9/16/2014.
(c) University of Washington10-1 CSC 143 Java Errors and Exceptions Reading: Ch. 15.
Exceptions Lecture 11 COMP 401, Fall /25/2014.
Terms and Rules II Professor Evan Korth New York University (All rights reserved)
Chapter 9: Continuing Classes By Matt Hirsch. Table Of Contents 1.Static Fields and Methods 2.Inheritance I. Recycle Code with Inheritance II. Overriding.
10-Jun-16.  Refactoring is: ◦ restructuring (rearranging) code... ◦...in a series of small, semantics-preserving transformations (i.e. the code keeps.
CSCE 240 – Intro to Software Engineering Lecture 3.
Lecture 6:Interfaces and Abstract Classes Michael Hsu CSULA.
Inheritance and Polymorphism
Chapter 11 Object-Oriented Design
Refactoring II 21-Sep-18.
Simple UML 11-Nov-18.
Simple UML 7-Dec-18.
Improving the structure of existing code
Refactoring II 5-Feb-19.
Review of Previous Lesson
Refactoring.
Presentation transcript:

17-Oct-15 Design Patterns and Refactoring CSC 2053

2 Buzzwords describe the higher-level organization of solutions to common problems Design Patterns describe the higher-level organization of solutions to common problems Design Patterns are a current hot topic in O-O design

Design Patterns Design Patterns are always described in UML notation UML is a diagramming language designed for Object-Oriented programming Design Patterns are used to describe refactorings 3

4 Design Patterns Refactoring is restructuring code in a series of small, semantics-preserving transformations (i.e. keeps the code working) in order to make the code easier to maintain and modify Refactoring often modifies or introduces Design Patterns

5 UML UML stands for Unified Modeling Language UML is a complicated diagramming language designed for Object-Oriented programming

UML UML comprises at least seven or eight different kinds of diagrams that can be used to describe: the organization of a program how a program executes how a program is used how a program is deployed over a network …and more We will just deal here with the class diagram 6

7 UML class diagrams Key: + means public visibility # means protected visibility - means private visibility means default (package) visibility static variables are underlined Name of the class Variables [optional] Methods Card cardId:int -copy:boolean=false «constructor» Card(int id) +isKind(desiredKind:int) +isSharable():boolean +toString():String Example:

8 UML relationships A B Class B extends class A C D 1..4 Class C contains 1 to 4 objects of class D Factory Product creates Other kinds of relations A B Class B implements interface A

9 Design patterns It is important in designing object-oriented software that you develop: a good design, that is reusable, able to address future problems.

Design Patterns Many design patterns have been established over the years that can help you do this. Good software developers reuse solutions that have worked in the past. So you will find recurring patterns of classes and communicating objects in many systems. 10

11 Problem I: Uncertain delegation Through polymorphism you can just send a message to an object, and the object does the right thing, depending on its type However, you must check first that the object is not null: if (myObject != null) myObject.doSomething();

EXAMPLES OF NULL OBJECTS You have an Ocean, represented by a sparse array containing a few Fish You have a TrafficGrid, some cells of which contains Cars and Trucks and others are empty You want to send output to some port potentially closed 12

NULL OBJECTS If you use these types of objects a lot: your code can end up cluttered with tests for null We need a Design Pattern to help us We need a Design Pattern to help us 13

14 Solution: Null Object So create another kind of object, a “null object,” representing the absence of any other kind of object E. G.: An Ocean might contain Inhabitant s So class Inhabitant can be sub classed by BigFish, LittleFish, Algae, and NothingButWater

INHABITANTS HIERARCHY 15 ABSTRACT CLASS INHABITANTS LittleFish Big Fish Nothing But Water abstract void REPRODUCE(); REPRODUCE() { SOME CODE} REPRODUCE() { SOME CODE}; REPRODUCE() ; NO CODE; So class Inhabitant has three sub classes: 1. BigFish, 2. LittleFish, Algae, and NothingButWater

Null Object This way, no location in the Ocean is null If Inhabitant class contains a method reproduce(), the subclass NothingButWater could implement this method with an empty method body 16

17 Refactoring: Introduce Null Objects The general idea is simple, refactor: Instead of having some variables (locations in the array) be null, have them be “null objects” However, this may require numerous changes in the code

Refactoring Changing working code is hazardous — you introduce bugs that it can take days to find. Solution: REFACTOR 18

19 Refactoring: to make it safe do: Refactoring has three pillars: Introduce the Null Objects in small steps, having an automated set of unit tests, and running unit tests frequently, so when errors occur you can pinpoint it immediately

20 Introduce Null Object: In detail 1.Create a subclass of the source class to act as a null version of the class.  Create an isNull() method in the source class and in the Null class.  For the source class it should return false, for the Null class it should return true.  All other subclasses of the source will inherit its version

21 Source Class > isNull() Null Class isNull() return True IsNull() as an Abstract method isNull() return False Normal class

22 IsNull() is not an abstract method Source Class boolean isNull() return false Null Class isNull() return True isNull() Is inherited Normal class The Null class overrides the parent class isNull() method

Null Object After creating the Null Object class: 1.Compile. 2.Find all places that produce a null when asked for a source object. 3.Replace them with a null object instead. 4.Replace one source and its clients at a time 23

24 Introduce Null Object: In detail, II 1.When the result is null for an operation, 2.do some alternative behavior instead. 3.E.g. return a string “Nothing But Water”. 4.For each of these cases, override the operation in the Null class with the alternative behavior. 5.Compile, and test.

25 Source Class > isNull() Null Class isNull() return True isNull() Return False Normal class INSTEAD OF THIS CODE : isNull() Return False Normal class

26 boolean isNull() return false isNull() return “Nothing but Water” Null Class Normal Class isNull() Is inherited USE AN ALTERNATIVE BEHAVIOR

27 Refactoring details IMPORTANT: Use “baby steps” Do the refactoring a little at a time, so that it’s very easy to catch and correct errors

USE TESTS THAT ARE already implemented. IMPORTANT - USE a good set of : totally automated tests — already implemented. Otherwise the testing is just too much work, and you won’t do it Otherwise the testing is just too much work, and you won’t do it JUnit is a great start 28

29 Scenario: Big fish and little fish The scenario: “big fish” and “little fish” move around in an “ocean” Fish move about randomly A big fish can move to where a little fish is (and eat it) A little fish will not move to where a big fish is

30 BigFish move() Fish > move() LittleFish move() We implement move methods in sub classes which are almost the same

31 Problem: Similar methods in subclasses We have a Fish class with two subclasses, BigFish and LittleFish The two kinds move the same way except a little fish won’t move near a big fish. To avoid code duplication, the move method ought to be in the superclass Fish

Problem - Since a LittleFish won’t move to some locations where a BigFish will move The test for whether it is OK to move really ought to be in the move method in the sub classes More generally, you want to have almost the same method in two or more sibling classes 32

33 The move() method General outline of the method: public void move() { choose a random direction; // same for both find the location in that direction; // same for both check if it’s ok to move there; // different if it’s ok, make the move; // same for both }

34 The Fish refactoring – Phase 1 BigFish move() Fish > move() LittleFish move() Note how first version works: When a BigFish tries to move, it overrides the move() method it inherits from Fish

35 Solution - Template Method  Write the oktoMove() method as an abstract method in the super class  This in turn requires that the super class be abstract

ReFactoring -step by step To refactor: Extract the check on whether it’s ok to move In the Fish class, put the actual (template) move() method Create an abstract okToMove() method in the Fish class Implement okToMove() differently in each subclass 36

37 The Fish refactoring: Phase II BigFish move() Fish > move() LittleFish move() BigFish okToMove(locn):boolean Fish move() : implemented > okToMove(locn):boolean LittleFish okToMove(locn):boolean Note how revised version works: When a BigFish tries to move, it uses the move() method it inherits from Fish Big Fish and LittleFish implement their own okToMove(locn)

38 Template Design The Design Pattern is called “Template Method”; The refactoring is called “Form Template Method”.

39 Problem: Constructors create objects Constructors make objects. Constructors make objects. Only constructors can make objects. Only constructors can make objects. When you call a constructor of a class, When you call a constructor of a class, you will get an instance of that class. you will get an instance of that class.

Singleton classes Sometimes you want more flexibility than that— YOU WANT TO: o guarantee that you can never have more than one object of a given class o create an object only if you don’t already have an equivalent object o create an object without being sure exactly what kind of object you want 40

41 Constructors Although only constructors make objects You don’t have to call constructors directly— you can call a method that calls the constructor for you Several “creational” Design Patterns are based on this observation

42 Singleton Design Pattern – A Creational Design Pattern A Singleton Design pattern provides a model for building a class that can have only one instance You may want just one instance of a null object, which you use in many places Or - to create just one AudioStream, so you can only play one tune at a time

Singleton Design Pattern You may want to have many printers but one spooler You might want to have one copy of alphabetic characters in a document 43

Singleton classes The method : define a static reference variable of the class type which serves as the single instance of the class. Make the constructor private so a user can not instantiate the class Use a static public method that returns the reference to the object 44

45 Singleton Design Pattern class Singleton { // create a single instance of the class private static Singleton instance = new Singleton(); // don’t let Java give you a default public constructor private Singleton() { } // Have a method that returns the instance of the class public static Singleton getInstance() { return instance; }... } See Dice.java

46 Singleton Design Pattern public class Dice { // static reference dice identifies the single class instance private static Dice dice = null; private Random rnd; private int dice1, dice2; // private constructor is called by the method getDice() // to create a single instance of the class private Dice() { // create a random number generator rnd = new Random(); }

47 Singleton Design Pattern /* if no object currently exists, the method calls the private constructor to create an instance; if an object exists, method returns the static reference variable*/ public static Dice getDice() { if (dice == null) { dice = new Dice(); // create a single dice object } return dice; // the single reference to the class } // other methods in the class

48 The Factory Method Design Pattern Suppose you write a class that works with several different kinds of objects You can do this if the classes all have a common interface You may want to be able to create objects, without being dependent on the kind of object A factory method can create instances of different classes, depending (say) on its parameters

FACTORY DESIGN PATTERN Example: public Image createImage (String ext) { if (ext.equals("gif")) return new GIFImage(); if (ext.equals("jpg")) return new JPEGImage();... } Note that it is not known beforehand what KIND of object will be created. 49

50 The Immutable Design Pattern There are many benefits to objects that cannot be changed after they have been created Such objects are called immutable Objects that refer to an immutable object never have to worry about whether that object has been changed Immutable objects are thread-safe—this is a significant efficiency concern, because synchronization is expensive

51 immutable objects Example: String s in Java It’s easy to make immutable objects in Java: Make all instance variables private, and Provide no methods that change those variables. Therefore you will have no setter methods

52 Delegation (or, when not to use inheritance) When you create a subclass, you agree to inherit all its (non-private) fields and methods What if you don’t want them all? Example: A Vector can do everything that a Stack should be able to do, and much, much more

Delegation You may want to inherit just some of the functionality, and probably add some of your own Inheritance doesn’t let you do that—at least, not easily 53

54 Delegation If your class wants to hide variables or methods inherited from a superclass, it shouldn’t inherit from that superclass If an object needs to be a different subclass at different times (say, a LittleFish turning into a BigFish), then it shouldn’t be a subclass of that class in the first place

Delegation Instead of inheriting, just use an instance of that class, and delegate to it what needs to be done In the next example, the stack class should not extend Vector – why???? 55

56 Example: Stacks class Stack { Vector contents = new Vector(); public void push(Object o) { contents.add(o); // delegate to the Vector } public Object pop() { return contents.remove(contents.size() – 1); }... }

57 Design vs. coding “Design” is the process of determining, in detail, what the finished product will be and how it will be put together “Coding” is following the plan

DESIGN In traditional engineering (building bridges), design is perhaps 15% of the total effort In software engineering, design is 85-90% of the total effort By comparison, coding is cheap 58

59 The refactoring environment Traditional software engineering is modeled after traditional engineering practices (design first, then code) Assumption: The desired end product can be determined in advance

60 Refactoring Refactoring is: restructuring (rearranging) code......in a series of small, semantics-preserving changes (i.e. the code keeps working)......in order to make the code easier to maintain and modify

61 Refactoring Refactoring is not just any old restructuring You need to keep the code working You need small steps that preserve semantics You need to have unit tests to prove the code works There are numerous well-known refactoring techniques

62 When to refactor When can you refactor? You should be in a supportive environment (agile programming team, or doing your own work) You should have an adequate set of automatic unit tests

63 When to refactor You should not refactor: Stable code (code that won’t ever need to change)

64 The refactoring environment “Agile” software engineering is based on different assumptions: Requirements (and therefore design) change as users become acquainted with the software

65 The refactoring environment Refactoring is fundamental to agile programming Refactoring is necessary when the design is found to be flawed It is advisable to refactor the design - designs should not be immutable

66 A personal view Design, because it is a lot more creative than simple coding, is also a lot more fun Most programming methodologies do not encourage good programming. Very good programmers find ways to improve the methodologies

67 Back to refactoring When should you refactor? Any time you find that you can improve the design of existing code You detect a “bad smell” (an indication that something is wrong) in the code

Refactor? When can you refactor? You should be in a supportive environment (agile programming team, or doing your own work) You should have an adequate set of automatic unit tests 68

69 Example 1: switch statements switch statements are very rare in properly designed code Therefore, a switch statement is a simple and easily detected “bad smell” Of course, not all uses of switch are bad A switch statement should not be used to distinguish between various kinds of object The simplest refactoring for this case is the creation of subclasses

70 Example 1, continued class Animal { final int MAMMAL = 0, BIRD = 1, REPTILE = 2; int myKind; // set in constructor... String getSkin() { switch (myKind) { case MAMMAL: return "hair"; case BIRD: return "feathers"; case REPTILE: return "scales"; default: return "integument"; } } }

71 Example 1, improved class Animal { String getSkin() { return "integument"; } } class Mammal extends Animal { String getSkin() { return "hair"; } } class Bird extends Animal { String getSkin() { return "feathers"; } } class Reptile extends Animal { String getSkin() { return "scales"; } }

72 How is this an improvement? a new animal type, such as Amphibian, does not require revising and recompiling existing code Mammals, birds, and reptiles are likely to differ in other ways, we’ve separated them out (so no more switch statements)

REfactoring We’ve gotten rid of the flags we needed to tell one kind of animal from another We’re now using Objects the way they were meant to be used 73

74 JUnit tests As we refactor, we need to run JUnit tests to ensure that we haven’t introduced errors, e.g. public void testGetSkin() { assertEquals("hair", myMammal.getSkin()); assertEquals("feathers", myBird.getSkin()); assertEquals("scales", myReptile.getSkin()); assertEquals("integument", myAnimal.getSkin()); } This should work equally well with either implementation

75 Bad Smell Examples We should refactor any time we detect a “bad smell” in the code Examples of bad smells include: Duplicate Code Long Methods Large Classes Long Parameter Lists Multi -location code changes

76 The End