Presentation is loading. Please wait.

Presentation is loading. Please wait.

Outline A. What is Refactoring? B. Why do we Refactor?

Similar presentations


Presentation on theme: "Outline A. What is Refactoring? B. Why do we Refactor?"— Presentation transcript:

1 Outline A. What is Refactoring? B. Why do we Refactor?
C. How do we Refactor? D. When do we Refactor? Here we will answer a few questions regarding refactoring such as what it is, why we care to do this to code, how it is done and when you will know in your program that refactoring is needed.

2 What is Refactoring? Refactoring is a technique which allows for the re-structuring of object-oriented code into classes and methods that are more readable, modifiable, and generally sparse in code. Refactoring yields a “better” design. There are many definitions of refactoring but for this class we will use the one published here.

3 B. Why do we Refactor? Refactoring allows building of complex systems by exploiting sophisticated object-oriented techniques that yield such systems catagorized as frameworks, beans, or other reusable software components. If you are writing a simple program this will seem like a lot of effort for nothing. But for complex systems, you NEED to have techniques to allow you to abstract solutions and reuse components. After all in the university system, how many times do you think the system might have the code to make a deciion regarding your classification. One instance is to determine if you can take a particular number of hours without advisor, chairs, or deans permission since there are rules regarding max limits on number of hours for each classification. If you try to register for a graduate course, it would check your classification to see if you need permission. When they calculate fees, there may be specific fees for grad/undergrad/special students. When you are assigned an advisor, the classification may make a difference. Wow, that is a lot of times you might write the code to determine the classification. Now lets say the university adds another classifcation called fast track where a student is classified as a undergraduate/graduate allowing them to take more hours, have different fees, taked grad courses, hmmmm there are a lot of places where I now have to change those if statements the same ones…..perhaps there is a better way so I do not have to have a large ripple effect for such a “simple change”.

4 How do we Refactor? Refactoring is accomplished by
building, decomposing, and moving methods building and decomposing classes replacing code with patterns, and replacing code with other techniques. One of the most common refactoring techniques deals with method manipulation. As you become better at refactoring, you begin to realize just how small a method should be to be a tightly cohesive, loosely coupled, reusable method. As we progress, we come across one of the major blocks for OO design, how do we build class…what is and is not a class.. We will show how refactoring helps in this endeavor looking at hightly reusable classes that are easily maintainable. As you refactor, you begin to see how many of the patterns fit into your code and the previous refactorings make it easy to do.

5 D. When do we Refactor? Refactoring is done when
methods or classes are too LARGE, code, control flow, or data structures are DUPLICATED, attributes or methods are MISPLACED, When parameters can make code reusable When design is poor. We factor when code smells and it smells it methods or classes are too large. What is too large. Some people maintain that no method should be over 10 lines of executable code some think less. When I use the word executable here, it excludes calls that execute in another method or class. It also smells if you see duplicated code such as asking what classifcation a student is. It smells if attributes or methods are always in a class that you do not need in your application. It smells when methods are coded with parameters that make that code not able to be used by others. It smells when the overall method and class design is difficult to manage… Rebecca Wirths Brock does a roseta map of code and the more lines present, the poorer the design.

6 An example- Class Diagram
Movie getPriceCode)_ setPriceCode() getTitle() pricecode: int children = 2 regular = 0 new_release=1 title: String Rental getMovie() getDaysRented)_ daysRented:int Customer Statement() addRental(rental) getName(): name: String rentals: vector We begin with an example class diagram for a Video Rental System (VRS) We have a movie that is documented as rented in Rental by a customer 0..* 1..1 1..1 0..*

7 An Example – Sequence Diagram
Customer Rental Movie statement Now we look at a sequence diagram to show how a rental might work then we will look at the methods to see how “good” the methods and classes actually are. forallrentals Rental: getMovie() getPriceCode() getDaysRented()

8 Code -- page 3 Constructor Movie public class Movie {
getPriceCode)_ setPriceCode() getTitle() pricecode: int children = 2 regular = 0 new_release=1 title: String public class Movie { public static final int CHILDRENS = 2; // type movie for children public static final int REGULAR = 0; // type of regular movie public static final int NEW_RELEASE = 1; // new release movie private String _title; // title of the movie private int _priceCode; // price code for movie public Movie(String title, int priceCode) { _title = title; _priceCode = price Code; }// end constructor public int getPriceCode() { return priceCode; } public void setPriceCode (int agr) { _priceCode = arg; } public String getTitle () { return _Title; } } // end Movie Here we look at the movie class wih a constructor for the simple movie (sure this would not be all the code). Then we have a few other gets and sets. Constructor

9 Code (con’t)-- page 3 Constructor Rental class Rental {
getMovie() getDaysRented)_ daysRented:int class Rental { private Movie _movie; // movie rented private int _daysRented; // number of days rental public Rental(Movie movie, int daysRented) { _movie = movie; _daysREnted = daysRented; } // end Rental public int getDaysRented() { return _daysRented; } public Movie getMovie() { return _movie; } }// end Rental Then we see the rental class where athe constructor takes a movie and the number of days rented as params – again simple for a simple example Constructor

10 Code (con’t)-- page 4 Constructor Customer class Customer {
Statement() addRental(rental) getName(): name: String rentals: vector Code (con’t)-- page 4 class Customer { private String _name; // name of customer private Vector _rentals = new Vector (); // vector of list of rentals by the customer public Customer (String name) { _name = name; } public void addRental (Rental arg) { _rentals.addElement(arg) } public String getName () { return _name} Now we see the customer Constructor

11 Code (con’t)-- page 5 public String statement() {
double totalAmount = 0; // total of the statement int frequentRenterPoints = 0; // number of frequent rental points of a rental Enumeration rentals = _rentals.elements(); // list of rentals String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); // continued on next page Now we have a method in customer called statement which traverses down the rentals for the statement

12 Code (Con’t) page 5 // determine amounts for each line // regular 2.00 for two days 1.50 extra // new release 3.00 per day // children 1.50 for three days & 1.50 if over 3 days switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: // statements for a regular movie thisAmount +=2; if (each.getDaysRented() >2) thisAmount +=(each.getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: // statements for a new release type movie thisAmount +=each.getDaysRented()*3; case Movie_CHILDREN: // statements for a children movie thisAmount +=1.5; if (each.getDaysRented() >3) thisAmount +=(each.getDaysRented()-3)*1.5; } // end switch Depending on the type of movie the fee is assessed

13 Code (Con’t) page 5 // add frequent renter points add 1 frequent renter point if NEW RELEASE rented > one day frequentRenterPoints ++; // add bonus for a two day new release rental if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) frequentRenterPoints ++; // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(thisAmount) + “\n”; totalAmount +=thisAmount; } // add footer lines result +=“Amount owed is “ + String.valueOf(totalAmount) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints) + “ frequent renter points”; return result; } // end statement // end customer And some frequent renter points are assigned

14 This method, statement, is TOO LARGE.
This statement method should not be inside customer. Well if we use our 10 loc this is certainly too large And what does the statement have to do with customer…. Has more to do with rental or maybe it should be in yet another class

15 Refactoring Opportunities
a code cluster is setting one variable // determine amounts for each line switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: thisAmount +=2; if (each.getDaysRented() >2) thisAmount +=(each.getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: thisAmount +=each.getDaysRented()*3; case Movie_CHILDREN: thisAmount +=1.5; if (each.getDaysRented() >3) thisAmount +=(each.getDaysRented()-3)*1.5; } // end switch EXTRACT it as a METHOD returning the variable If we look at the assessment of a fee depending on the type of movie, we notice that each little group of code is simply setting the variable of the fee

16 EXTRACT METHOD page 11 private double amountFor(Rental each)
double thisAmount = 0.0; switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: thisAmount +=2; if (each.getDaysRented() >2) thisAmount +=(each.getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: thisAmount +=each.getDaysRented()*3; case Movie_CHILDREN: thisAmount +=1.5; if (each.getDaysRented() >3) thisAmount +=(each.getDaysRented()-3)*1.5; } // end switch return thisAmount; } // end amountFor EXTRACT METHOD page 11 Perhaps we should extract this method so that we could easily test it by sending different types of movies and getting the fee. We could test it as a unit rather than testing it inside code that is doing many things.

17 Original Code - Customer Class page 18
public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = amountFor(each); Now we can add this code to call the method to get the fee Calls the new method

18 Refactoring Opportunities
a variable resides in the wrong class MOVE the METHOD to the class where it should reside public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = amountFor(each); Where should this class reside Should NOT be in customer class Should be in the rental

19 Rename the method and result
private double getCharge(Rental each) double result = 0.0; switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: result +=2; if (each.getDaysRented() >2) result +=(each.getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: result +=each.getDaysRented()*3; case Movie_CHILDREN: result +=1.5; if (each.getDaysRented() >3) result +=(each.getDaysRented()-3)*1.5; } // end switch return result; } // end getCharge MOVE METHOD and rename Rename the method and result Soo lets move the method and rename it to be more meaningful

20 Original Code - Customer Class page 19
public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = each.getCharge(each); Calls the new method In the rental class And add the calls to the new method

21 An Example – Sequence Diagram
Customer Rental Movie statement Now the sequence diagram changes forallrentals Rental: getMovie() amount: getCharge() getPriceCode() getDaysRented()

22 Refactoring Opportunities
a code cluster is setting one variable EXTRACT it as a METHOD returning the variable } // add frequent renter points add 1 frequent renter point if NEW RELEASE rented > one day frequentRenterPoints ++; // add bonus for a two day new release rental if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) frequentRenterPoints ++; // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(thisAmount) + “\n”; totalAmount +=thisAmount; } // add footer lines result +=“Amount owed is “ + String.valueOf(totalAmount) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints) + “ frequent renter points”; return result; } // end statement In the next few pages there are several examples that you can view… The intent here is NOT to totally understand this example but to get an introduction to the different types of refactorings….we will cover them in detail later.

23 EXTRACT METHOD // add frequent renter points add 1 frequent renter point if NEW RELEASE rented > one day int getFrequentRenterPoints() { if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) return 2; else return 1;

24 Refactoring Opportunities
a variable resides in the wrong class MOVE the METHOD to the class where it should reside public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += getFrequentRenterPoints(); Should NOT be in customer class Should be in the rental

25 MOVE METHOD class Rental….. …..
// add frequent renter points add 1 frequent renter point if NEW RELEASE rented > one day int getFrequentRenterPoints() { if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) return 2; else return 1;

26 Original Code - Customer Class
public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = each.getCharge(); frequentRenterPoints += each.getFrequentRenterPoints(); Calls the new methods In the rental class

27 Refactoring Opportunities
a variable is used temporarily REPLACE TEMP with QUERY eliminating the temp public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = each.getCharge(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(thisAmount) + “\n”; totalAmount +=this.Amount; } // end while

28 REPLACE TEMP with QUERY page 21
public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { double thisAmount =0; Rental each = (Rental) rentals.nextElement(); thisAmount = each.getCharge(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(thisAmount each.getCharge()) + “\n”; totalAmount += this.Amount each.getCharge() ; } // end while

29 Refactoring Opportunities
a variable is used temporarily REPLACE TEMP with QUERY public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(each.getCharge()) + “\n”; totalAmount += each.getCharge(); } // end loop // add footer lines result +=“Amount owed is “ + String.valueOf(totalAmount) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints) + “ frequent renter points”; return result; } // end statement eliminating the temp Problem – temp in loop

30 EXTRACT it as a METHOD private double getTotalCharge() {
double result = 0; Enumeration rentals = _rentals.elements(); while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); result += each.getCharge(); } // end loop return result; } // end getTotalCharge

31 REPLACE TEMP with QUERY page 27
public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(each.getCharge()) + “\n”; totalAmount += each.getCharge(); } // add footer lines result +=“Amount owed is “ + String.valueOf( totalAmount getTotalCharge()) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints) + “ frequent renter points”; return result; } // end statement Yes, we are looping twice

32 Refactoring Opportunities
a variable is used temporarily REPLACE TEMP with QUERY public String statement() { int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(each.getCharge()) + “\n”; } // end loop // add footer lines result +=“Amount owed is “ + String.valueOf(getTotalCharge) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints) + “ frequent renter points”; return result; } // end statement eliminating the temp Problem – temp in loop

33 EXTRACT it as a METHOD private double getTotalFrequentRentalPoints() {
int result = 0; Enumeration rentals = _rentals.elements(); while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); result += each.getFrequentRentalPoints(); } // end loop return result; } // end getTotalFrequentRentalPoints

34 REPLACE TEMP with QUERY page 29
public String statement() { int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = “Rental Record for “ + getName() +”/n” while (rentals.hasMoreElements() { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += getFrequentRenterPoints(); // show figures for this rental result +=“/t” + each.getMovie().getTitle*(+”\t” + String.valueOf(each.getCharge()) + “\n”; } // add footer lines result +=“Amount owed is “ + String.valueOf( getTotalCharge()) + “\n”; result += “You earned “ + String.valueOf(frequentRenterPoints getTotalFrequentRentalPoints ) + “ frequent renter points”; return result; } // end statement Yes, we are looping thrice

35 An Example – Sequence Diagram
Customer Rental Movie statement getTotalCharge amount: getCharge() getPriceCode() getFrequentRenterPoints() getPriceCode()

36 Refactoring Opportunities
conditional code exist for sub-types Use POLYMORPHISM replacing conditional logic private double getCharge(Rental each) double result = 0.0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result +=2; if (getDaysRented() >2) result +=(getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: result +=getDaysRented()*3; case Movie_CHILDREN: result +=1.5; if (getDaysRented() >3) result +=(getDaysRented()-3)*1.5; } // end switch return result; } // end getCharge Cannot make subclasses of movie Movies can change classifications

37 Refactoring Opportunities
object can change states in its lifetime Use the STATE Pattern for the variables which change values private double getCharge(Rental each) double result = 0.0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result +=2; if (getDaysRented() >2) result +=(getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: result +=getDaysRented()*3; case Movie_CHILDREN: result +=1.5; if (getDaysRented() >3) result +=(getDaysRented()-3)*1.5; } // end switch return result; } // end getCharge Cannot make subclasses of movie Movies can change classifications

38 Original- Class Diagram
Movie getPriceCode)_ setPriceCode() getTitle() pricecode: int children = 2 regular = 0 new_release=1 title: String Rental getMovie() getDaysRented)_ daysRented:int Customer Statement() addRental(rental) getName(): name: String rentals: vector 0..* 1..1 1..1 0..*

39 State Pattern- Class Diagram
Price getCharge() 1..1 Movie getPriceCode)_ setPriceCode() getTitle() getCharge() pricecode: int children = 2 regular = 0 new_release=1 title: String 1..1 Regular Price getCharge() Childrens Price getCharge() New Release Price getCharge()

40 Refactoring Opportunities
state variables not encapsulated SELF ENCAPSULATE FIELDS add get and set methods private double getCharge(int daysRented) double result = 0.0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result +=2; if (getDaysRented() >2) result +=(getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: result +=getDaysRented()*3; case Movie_CHILDREN: result +=1.5; if (getDaysRented() >3) result +=(getDaysRented()-3)*1.5; } // end switch return result; } // end getCharge Cannot make subclasses of movie Movies can change classifications

41 } Sub-types Original Code -- page 3 Self Encapsulate
public class Movie { public static final int CHILDRENS = 2; public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; private String _title; private int _priceCode; public Movie(String title, int priceCode) { _title = title; _priceCode = price Code; }// end constructor public int getPriceCode() { return priceCode; } public void setPriceCode (int agr) { _priceCode = arg; } public String getTitle () { return _Title; } } // end Movie } Sub-types Self Encapsulate

42 Self Encapsulating Movie Code -- page 41
public class Movie { public static final int CHILDRENS = 2; public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; private String _title; private int _priceCode; setPriceCode(priceCode); public Movie(String title, int priceCode) { _title = title; _priceCode = price Code; }// end constructor public int getPriceCode() { return priceCode; } public void setPriceCode (int agr) { _priceCode = arg; } public String getTitle () { return _Title; } } // end Movie

43 Movie Price Sub-Classes -- page 41
class Price { abstract int getPriceCode(); } // end Price class ChildrensPrice extends Price { int getPriceCode () { return Movie.CHILDRENS; } } // end ChildrensPrice class NewReleasePrice extends Price { int getPriceCode () { return Movie.NEW_RELEASE; } } // end NewReleasePrice class RegularPrice extends Price { int getPriceCode () { return Movie.REGULAR; } } // end RegularPrice

44 MOVE METHOD page 45 class Price private double getCharge(int daysRented) double result = 0.0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result +=2; if (getDaysRented() >2) result +=(getDaysRented()-2)*1.5; Break; case Movie.NEW_RELEASE: result +=getDaysRented()*3; case Movie_CHILDREN: result +=1.5; if (getDaysRented() >3) result +=(getDaysRented()-3)*1.5; } // end switch return result; } // end getCharge }// end price Once it is moved, we can replace conditional with polymorphism

45 Use POLYMORPHISM page 47 Take one leg of case statement at a time.
class RegularPrice double getCharge(int daysRented) double result = 2; if (getDaysRented() >2) result +=(getDaysRented()-2)*1.5; return result; } // end getCharge } // end regularPrice class ChildrensPrice double getCharge (int daysRented) { double result = 1.5; if (getDaysRented() >3) result +=(getDaysRented()-3)*1.5; return result } // end ChildrensPrice class NewRelease double getCharge (int daysRented() { return daysRented * 3; } Take one leg of case statement at a time.

46 Use POLYMORPHISM page 47 class Price abstract double getCharge (int daysRented); Create an overiding method for the getCharge method.

47 Use POLYMORPHISM page 48 class Movie….. int getFrequentRenterPoints (int daysRented) { if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented >1) return 2; else return 1; } We can do the same thing with getFrequentRenterPoints

48 Final Thoughts page 52 Placing a state pattern in code is quite an effort The gain is that if I change any of the price’s behavior add new prices add extra price dependent behavior The rest of the application does not know about the use of the state pattern. For this tiny bit of behavior, it does not seem worthwhile. These changes lead to better distributed responsibilities and code 1that is easier to maintain. It does look different than the regular procedural code. One important lesson in this example is the rhythm of refactgoring, change a little test a little This is pretty advanced thinking for the first of the course…no worries we will get there … Remember this is just an introductory overview lecture

49 Benefits of Refactoring
Without refactoring, the design of the program decays. Refactoring helps you to develop code more quickly. Refactoring helps you to find bugs. Refactoring makes software easier to understand. Refactoring improves the design of software. Some of the benefits are Preventing decay….the older code gets the further away from the original design the code gets until finally, all the structure is gone and the code is totally not readable or understandable. Regactoring helps this not to haappen. While it might appear that refactoring makes you slow down, once you get in the grove, code goes SO MUCH FASTER because you qauickly see reusable code, easier ways to test thus making development faster…. Maintenance gets easier since the code is easier to understand.

50 When do you refactor Refactor when you add functions.
Refactor as you do a code review. Refactor when you fix a bug.

51 Why do you refactor Enable sharing of logic.
Explain intention and implementation seperately. Isolate change. Encode conditional logic.

52 Catalogue of Refactoring
We will look at a catalogue of refactoring methods. Each refactoring method is described by the following: name : noun (with a page number of the text) summary : narrative description motivation : why you would use the technique example : code using the technique mechanics : how you would use the technique There is a WHOLE catalogue of refactorings and you will want to become acquainted with them.

53 We will look at several types of refactoring
We will look at several types of refactoring. These include the refactoring of: methods generalization classes data calls conditional expressions And some other BIG refactoring.

54 Refactoring and Composing Methods
Extract Methods from code Inline Methods to code Replace Temp with Query Introduce Explaining Variables Split Temporary Variables Remove Assignments to Parameters Replace Method with Method Objects Substitute Algorithm

55 Refactoring by Moving Features Between Objects
Move Method Move Field Extract Class Inline Class Hide Delegate Remove Middle Man Introduce Foreign Method Introduce Local Extension

56 Refactoring by Organizing Data
Self Encapsulate Field Encapsulate Field Replace Data Value with Object Encapsulate Collection Change Value to Reference Replace Record with Data Class Change Reference to Value Replace Type with Data Class Replace Array with Object Replace Type Code with Subclasss Duplicate Observed Data Replace Type Code with State/Strategy Change Unidirectional Direction to Bidirectional Replace Subclass Change Bidirectional Direction to Unidirectional with Field Replace Magic Number with Symbolic Constant

57 Refactoring by Simplifying Conditional Expressions
Decompose Conditional Consolidate Conditional Expression Consolidate Duplicate Conditional Fragments Remove Control Flag Replace nested Conditional with Guard Clauses Replace Conditional with Polymorphism Introduce Null Object Introduce Assertion

58 Refactoring by Making Method Calls Simpler
Rename Method Introduce Parameter Object Add Parameter Remove Setting Method Remove Parameter Hide Method Separate Query from Modifier Replace Constructor with Factory Parameterize Method Encapsulate Downcast Replace Parameter with Explicit Methods Preserve Whole Object Replace Error Code with Exception Replace Parameter with Method Replace Exception with Test

59 Refactoring by Dealing with Generalization
Pull Up Field Extract Interface Pull Up Method Collapse Hierarchy Pull Up Constructor Body Form Template Method Push Down Method Replace Inheritance with Push Down Field Delegation Extract Subclass Replace Delegation with Extract Superclass Inheritance

60 Refactoring with Big Refactoring
Tease Apart Inheritance Convert Procedural Design to Objects Separate Domain from Presentation Extract Hierarchy

61 Because there are SOOOO many factorings
We will approach these by having lessions on software engineering topics and integrating these refactorings into specific lessons on the topics.

62 Refactoring Topics Lesson One: Self-Documenting Code and Functional Testing Lesson Two: Encapsulation and Unit Testing Lesson Three: Constants and Variables Lesson Four: Methods Lesson Five: Conditionals Lesson Six: Classes Lesson Seven: Inheritance Lesson Eight: Patterns


Download ppt "Outline A. What is Refactoring? B. Why do we Refactor?"

Similar presentations


Ads by Google