How and When to do Refactoring CSE301 University of Sunderland Harry R. Erwin, PhD.

Slides:



Advertisements
Similar presentations
12-Dec-14 Refactoring IV. Previously discussed bad smells Duplicated code — and other forms of redundancy Long method — use short methods that delegate.
Advertisements

CS0007: Introduction to Computer Programming Introduction to Classes and Objects.
Composition CMSC 202. Code Reuse Effective software development relies on reusing existing code. Code reuse must be more than just copying code and changing.
Module 7. Simplifying Conditional Expressions Course: Refactoring.
Clean code. Motivation Total cost = the cost of developing + maintenance cost Maintenance cost = cost of understanding + cost of changes + cost of testing.
Test-Driven Development and Refactoring CPSC 315 – Programming Studio.
You want me to do what??? Refactoring legacy applications aka : fixing someone else’s “bad” code Niel Zeeman Team Foundation Consulting
Refactoring to Patterns CSE301 University of Sunderland Harry R Erwin, PhD.
Refactoring Overview  What is refactoring?  What are four good reasons to refactor?  When should you refactor?  What is a bad smell (relative to refactoring.
Lectures 17 and 18 A Refactoring Micro-Example FOR0383 Software Quality Assurance 5/16/20151Dr Andy Brooks Refactoring is really easy using this tool.
Georgia Institute of Technology Workshop for CS-AP Teachers Chapter 3 Advanced Object-Oriented Concepts.
Software Construction and Evolution - CSSE 375 Bad Smells in Code Shawn Bohner & Steve Chenoweth.
Introduction to Refactoring Excerpted from ‘What is Refactoring?’ by William C. Wake and Refactoring: Improving the Design of Existing Code by Martin Fowler.
Stacks. 2 What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything removed.
XP and Refactoring David Talby. Development Methodologies The Software Crisis – 84% of software projects are not on time – 31% of software projects never.
REFACTORING Improving the Design of Existing Code Atakan Şimşek e
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 Lecture 4. Definition Refactoring is a process of changing the internal structure of the program, not affecting its external behavior and.
CISC6795: Spring Object-Oriented Programming: Polymorphism.
What is Refactoring? CSE301 University of Sunderland Harry R. Erwin, PhD.
07 Coding Conventions. 2 Demonstrate Developing Local Variables Describe Separating Public and Private Members during Declaration Explore Using System.exit.
Refactoring. Mathematics: Factor ● fac·tor – One of two or more quantities that divides a given quantity without a remainder, e.g., 2 and 3 are factors.
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.
Small changes to code to improve it. Refactoring Defined A change made to the internal structure of software to make it easier to understand and cheaper.
Chapter 2 Introducing Interfaces Summary prepared by Kirk Scott.
Refactoring (continued) Source: "Refactoring: Improving the Design of Existing Code", Martin Fowler.
SWE 316: Software Design and Architecture Objectives Lecture # 20 Improving the existing design: Refactoring SWE 316: Software Design and Architecture.
Refactoring1 Improving the structure of existing code.
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.
1 CSC/ECE 517 Fall 2010 Lec. 3 Overview of Eclipse Lectures Lecture 2 “Lecture 0” Lecture 3 1.Overview 2.Installing and Running 3.Building and Running.
Software Engineering CS3003 Lecture 4 Code bad smells and refactoring.
Refactoring. Refactoring Overview  What is refactoring?  What are four good reasons to refactor?  When should you refactor?  What is a bad smell (relative.
Refactoring 2. Admin Blackboard Quiz Acknowledgements Material in this presentation was drawn from Martin Fowler, Refactoring: Improving the Design of.
REFACTORINGREFACTORING. Realities Code evolves substantially during development Requirements changes 1%-4% per month on a project Current methodologies.
Chapter 6 Introduction to Defining Classes. Objectives: Design and implement a simple class from user requirements. Organize a program in terms of a view.
Module 3. Smells Between Classes Course: Refactoring.
Behavioral Patterns CSE301 University of Sunderland Harry R Erwin, PhD.
Design Patterns Software Engineering CS 561. Last Time Introduced design patterns Abstraction-Occurrence General Hierarchy Player-Role.
1 Software Maintenance and Evolution CSSE 575: Session 3, Part 3 Dealing with Generalization Steve Chenoweth Office Phone: (812) Cell: (937)
SEG 4110 – Advanced Software Design and Reengineering Topic T Introduction to Refactoring.
Refactoring. Mathematics: Factor ● fac·tor – One of two or more quantities that divides a given quantity without a remainder, e.g., 2 and 3 are factors.
Data Design and Implementation. Definitions Atomic or primitive type A data type whose elements are single, non-decomposable data items Composite type.
CS 325: Software Engineering March 19, 2015 Applying Patterns (Part B) Code Smells The Decorator Pattern The Observer Pattern The Template Method Pattern.
CSSE 375 Organizing Data – Part 2 Shawn and Steve Continue the same quiz!
Refactoring1 Improving the structure of existing code.
Pertemuan 12 Refactoring Mata kuliah: T0144 – Advanced Topics in Software Engineering Tahun: 2010.
Refactoring. 2 Process of changing a software system in such a way that it does not alter the external behavior of the code, yet improves its internal.
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.
CSSE 375 Organizing Data – Part 1 Shawn and Steve Q1.
Refactoring. DCS – SWC 2 Refactoring ”A change made to the internal structure of software to make it easier to understand and cheaper to modify without.
Module 9. Dealing with Generalization Course: Refactoring.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
Chapter 9: Continuing Classes By Matt Hirsch. Table Of Contents 1.Static Fields and Methods 2.Inheritance I. Recycle Code with Inheritance II. Overriding.
CSCE 240 – Intro to Software Engineering Lecture 3.
Chapter 5 Introduction to Defining Classes Fundamentals of Java.
Catalog of Refactoring (6) Making Method Calls Simpler.
Principles and examples
Catalog of Refactoring
Module Road Map Refactoring Why Refactoring? Examples
Inheritance and Polymorphism
Chapter 11 Object-Oriented Design
Overview of Eclipse Lectures
Code Smells 1.
Improving the structure of existing code
Stacks.
Refactoring.
Presentation transcript:

How and When to do Refactoring CSE301 University of Sunderland Harry R. Erwin, PhD

Resources Eclipse automates a lot of refactoring (8)). Fowler, 2000, Refactoring: Improving the Design of Existing Code, Addison-Wesley. Note: this is available electronically at the library. / / http:// / / / http:// / ndex.phphttp:// ndex.php

Final Year Project Comments A few comments on OO programming. Important refactorings will be in dark blue. –Don't translate a C program into Java. Think objects. –Avoid overusing static fields and methods. That suggests you're writing a C program in Java. Don't go there. –Use 'move method' to push responsibilities into subclasses. Students often define methods in the calling classes rather than in the called classes, and then need to correct the design. –Look for polymorphism. It can be used rather elegantly. –Are you using JUnit and TDD? Use the existing suite and read the documentation about asserts!

Refactoring that Eclipse Supports Already! Rename Move Change Method Signature Convert Anonymous Class to Nested Class Change Nested Class to Top-Level Class Push Down Pull Up Extract Interface Use Supertype Where Possible Inline Extract Method Extract Local Variable Extract Constant Convert Local Variable to Field Encapsulate Field

A Catalog of Refactorings Composing Methods Moving Features Between Objects Organizing Data Simplifying Conditionals Making Method Calls Simpler Generalization Big Refactorings

The Basic Rule of Refactoring “Refactor the low hanging fruit” Low Hanging Fruit (def): “The thing that gets you most value for the least investment.” In other words, don’t spend much time on it. There are ways to improve any design incrementally. We will explore a few of them.

The Goal of Refactoring To improve code without changing what it does. This in some ways is similar to how an optimizing compiler restructures code. These how-to’s describe things you can do. Think about why they work!

Composing Methods Extract Method Inline Method Replace Method with Method Object Substitute Algorithm

Extract Method Extract Method is one of the most important refactorings. If you see a patch of coherent code that does something like compose a pane in a GUI encapsulate it as a method. This is my favorite refactoring; usually I apply it when a method gets too long. Take a clump of related code and make it into a small method. eclipse handles this well. It does have problems with local variables….

Example for Extract Method final JCheckBox oos = new JCheckBox( "Out of Supply ",unit.outOfSupply); ActionListener oosListener = new ActionListener(){ public void actionPerformed(ActionEvent e){ theUnit.outOfSupply = oos.isSelected(); theBattle.recompute(); } }; oos.addActionListener(oosListener); res.add(oos);

That Code Becomes final JCheckBox oos = addOOS(unit, theUnit); res.add(oos); AND private JCheckBox addOOS(Ground unit, final Ground theUnit) { final JCheckBox oos = new JCheckBox( "Out of Supply ",unit.outOfSupply); ActionListener oosListener = new ActionListener(){ public void actionPerformed(ActionEvent e){ theUnit.outOfSupply = oos.isSelected(); theBattle.recompute(); } }; oos.addActionListener(oosListener); return oos; }

Inline Method Reverses Extract MethodExtract Method You use Inline Method when the code the results from Extract Method is uglier than the original. You also use it when the method’s body is just as clear as its name. Or if you have a group of badly factored methods—inline them and then re-extract methods. Remember to get rid of the method—needless indirection is irritating and makes you look dumb.

Replace Method with Method Object Replace Method with Method Object moves local variables into class fields of a ‘functor’, so Extract Method can be used more easily.Extract Method The curse of extracting methods is local variables. So introduce method objects if you have a big method with lots of local variables. Applying this refactoring converts all those local variables to fields of the method object. Then you can extract methods freely.

Method Object Implementation (after Beck via Fowler) Create a new class named after the method. Define a final field for the object that owned the original method and a modifiable field for every local variable. Define a constructor with those fields as arguments. Give the class a method named ‘compute()’. Replace the old method with one that creates the object and calls compute(). int gamma(int val1, int val2, int val3) { return new Gamma(this,val1,val2,val3).compute(); } Now you can freely decompose compute() without passing any parameters. This is a good thing.

Substitute Algorithm This one sounds a bit dumb. Have you thought of a smarter or clearer way of doing something? Go ahead and replace the method with the new algorithm. If you’re using test-driven development, you can quickly check whether the new version works. If it doesn’t, backtrack, and nobody will ever know…

Moving Features Between Objects A fundamental design decision is where to put responsibilities. You’ll never get it right the first time. Refactoring allows you to change your mind. When you want to move functions between objects, these refactorings handle it. Move Method, Move Field, and Extract/Inline Class are the heavyweights here.

Move Field “Moving state and behavior between classes is the very essence of refactoring.” (Fowler) You do this to shuffle responsibilities around. Consider a move if a field is used more by other classes than by its home class. If you do an Extract Class, the fields get moved first and then the methods follow them.Extract Class You may need to encapsulate a field first. Then move the field and point any accessors at the new location, perhaps using new accessors there.encapsulate a field

Move Method “The bread and butter of refactoring.” (Fowler) A method is used by another class more than by its home class. I know of cats like that. Create a similar method in the other class. Either convert the old method to a simple delegation or remove it entirely. Think about doing this after you’ve moved some fields between classes. Warning: watch for polymorphism on the original class. That can make the move impossible.

Extract Class Classes grow, and you may have one class doing work that should be done by two. You find you’re violating the Single Responsibility Principle (SRP) with lots of data and methods. Time to get the scalpel out. Create a new class and move the relevant fields and methods there. Delegate! If you don’t know why the SRP is important, wait till next semester.

Inline Class You find a class isn’t doing very much. This often occurs after a refactoring that has removed fields and methods. Move its features into another class and then delete it. Use Encapsulate Field, Move Field, and Move Method to do this.Encapsulate FieldMove Field Move Method

Hide Delegate A client calls a method defined on a field of a server object, possibly violating encapsulation. theServer.getManager().getDepartment(); To do this, the client needs to know that theServer has a Manager field. Replace with a getDepartment() method for theServer. Then unless getManager() is needed, remove it. theServer.getDepartment();

Remove Middle Man “Here, you take the phone.” After some development, you notice that a class is doing a lot of simple delegation. Get the client to call the delegate directly. You may need to create an accessor for the delegate, but thereafter a method only needs to call on the delegate.

End of First Hour

Organizing Data These refactorings generally clean up problems with how classes define and access fields. The most interesting refactoring here is probably Duplicate Observed Data. That’s how you fix a class that mixes business logic with GUI or SQL code. We’ll spend some time on it since Fowler isn’t very clear. Duplicate Observed Data By the way, value objects are objects that are equal if their fields are equal—you override equals() and hashCode() for them.

Self Encapsulate Field You are accessing a field of a class directly in a method, but use of the field is becoming awkward. Create getting and setting methods (‘accessors’) for the field and make the field private. Use these methods within the class. Why not always do this? Because getting and setting methods obscure what the code is doing. Doing this is particularly important if a subclass may later need to override direct access with a computed value. A closely related refactoring: Encapsulate Field.Encapsulate Field.

Replace Data Value with Object You find that you have a data item (a primitive or value type) that needs additional data or behavior. For example, the data might be a String that has a special format. Turn the data item into an object that holds the original data as a final field. Provide a constructor and a getting method. If you need a setting method, have it create a new instance of the class. You may need to Change Value to Reference, if multiple instances need to share the data object.Change Value to Reference

Reference objects stand for one object in the real world. Value objects are defined entirely through their data values. You need to know when two are equal, so you have to override equals() and hashCode(). A class has many instances, many of which have the same value. You want to replace them with a single instance. –Replace the value constructor with a factory method. –Decide how to provide access to the objects. –Decide whether to precreate or create as required. –Alter the factory method to return the reference object.

Change Reference to Value You have a reference type object that is small, immutable, and awkward to manage. Turn it into a value object. –Check that it is really immutable (final) or can become immutable. –Create an equals() and a hashCode() method. The easiest way to write hashCode() is to do a bitwise xor (^) on all the hashcodes of the fields referred to in the equals() method. Primitive types need to be ‘boxed’ for this. E.g., to box i, Integer iBoxed = new Integer(i); –The consider removing the factory method and replacing it with a public constructor. –Finally make the contents final.

Replace Array with Object You have inherited a design that uses an array where different elements mean different things. This is bad programming practice. Replace with an object that has a field for each element. You do this by creating getters and setters for each entry in the array, creating the fields, and then removing the array and repointing the getters and setters at the new fields.

Duplicate Observed Data This is how you pull a domain model (the business logic) out of a poorly-designed system with no model. If there are multiple windows, see Separate Domain from Presentation. Separate Domain from Presentation. Copy the business data in the system to a domain object. Set up observers to synchronize the domain model with whatever is dependent on it. This is a tricky dribble, so pay close attention.

DOD Implementation (Part 1) Start with the dependent objects (e.g., parts of the GUI, other interfaces or a database). Create a domain class as an Observable. Create references to the dependent objects in the domain class. Make the dependent objects Observers of the domain class, so that if it changes, they change. Write an update() method for each. Each constructor has to connect to the domain class, add itself as an Observer of that class, and finally call its update() method on the domain class instance. Use Self-Encapsulate Data on any domain data in the dependent objects. Test—behavior should not change.Self-Encapsulate Data

DOD Implementation (Part 2) Now for GUIs, add a method to the event handler that uses the new setting methods to update the component with its current value using direct access to the field. This ensures user input goes through the setting method. This will be important later. Test. Define corresponding data fields and getting/setting methods in the domain class. Setting methods need to trigger model updates and the notify mechanism. Test. Redirect the accessors for the dependent classes to read and write the domain class fields. Modify the observer’s update method to copy from the domain fields to the dependent class using direct access. Test one last time.

Change Unidirectional to Bidirectional Association You need a backpointer? First, lie down to see if the need passes. If it doesn’t, do the following: –Add a field for the backpointer. –Decide which class controls the link. –Create a helper method on the other side to send back the backpointer. –If the existing link modifier is on the controlling side, just modify it to update the backpointers. –If not, have it call a routine on the other side to update the backpointers.

Change Bidirectional to Unidirectional Association Reduce bidirectional to unidirectional whenever possible. If nobody needs one direction, simply remove it. For clients who do need the other direction: –Try Encapsulate Field on the backpointerEncapsulate Field –Then try Substitute Algorithm on the getter and testSubstitute Algorithm –If clients don’t need the getter, change each to get the object in the field some other way. –When no reader is left, dump the updater and remove the backpointer.

Encapsulate Field A class field is publically accessible. Hide it. Some people consider this good programming practice. Other people find it makes code inefficient or hard to read. YMMV. Provide accessors—getField(), setField(arg) Then find all users and change them to use the accessors. Finally, make the field private. This will tell you if you have really found all the users. Closely related to Self Encapsulate Field.Self Encapsulate Field

Encapsulate Collection If a class contains a collection of instances, getters and setters don’t work really well. First, initialize an empty collection when you create it. Encapsulate the collection field to create a getter and setter.Encapsulate the collection field Next provide public methods to add and remove elements. Modify users to use them instead. Modify your getter to return a read-only iterator (see the Collections class for how). Think about moving code that uses the getter into the class that owns the collection.

Replace Type Code With Class –When a class has a numeric type code that doesn’t affect its behavior—replace with a new class for each code. With Subclasses –If the type code does affect behavior, use subclasses With State/Strategy –Or replace the type code with a state object if subclassing doesn’t work

Replace Subclass with Fields You have subclasses that differ only in methods that return constant (final) data. Define final fields to contain the data, eliminate the subclasses, and return the field values instead.

Simplifying Conditionals These simplify conditional logic (if/then/else). Decompose Conditional is the most important. The elements of an if/then/else are replaced with method calls. These refactorings can also clean up if/then/else messes where flags are used to control sequencing or returns. Decompose Conditional Switch statements should be replaced with polymorphism. A null object is a real ‘do-nothing’ object that substitutes for a null value in a reference.

Decompose Conditional Suppose you have a complicated if-then- else (or ?:) statement. Use Extract Method on the condition, the then part, and the else part.Extract Method If there is a nested conditional, try Replace Nested Conditional with Guard Clauses first.Replace Nested Conditional with Guard Clauses

Consolidate Conditional Expression If you have a long list of ‘if(cond i ) return 0;’ statements in a method, combine them into a single conditional and extract it. This does the same thing, is clearer, and sets you up to use Extract Method.Extract Method.

Consolidate Duplicate Conditional Fragments The same fragment of code is in all branches of a conditional expression. Then move it outside of the expression. This makes things clearer. Consider using Extract Method, too. Extract Method,

Replace Nested Conditional with Guard Clauses If a method contains a complicated if-then- else expression that doesn’t make clear what the normal path is, use ‘guard clauses’ for all the special cases. Handle each special case with an immediate return. Then execute the normal path. Be clear!

Replace Conditional with Polymorphism Indicator—you have logic that chooses different behavior based on the type of an object or the value of a flag. Consider splitting the behavior among subclasses. Make the original method abstract. You may have to replace type codes with subclasses or state/strategy first.

Introduce Null Object You’re getting very tired of checking for null. This is often the case for framework code. Then replace the null value with a do-nothing ‘null object’. (This is what an Adaptor class is in swing, by the way.) This has the advantage of inheriting from Object (or even from the base class of your hierarchy). Unlike null, a ‘null object’ can have do-nothing methods called on it. A lot of if-then-else cases then disappear.

Making Method Calls Simpler These refactorings make interfaces more straightforward. Rename Method is convenient to document what a method does.Rename Method Most of the remaining refactorings are used to get rid of parameters, but be cautious in concurrent programming. Factory methods hide the concrete implementation of an interface.

Rename Method You have a method with a name like ‘foo’. Change the name to mean something. This is important when you have lots of small methods as a form of documentation. eclipse handles this very well.

Separate Query from Modifier You have a method that returns a value but also changes the state of an object. This violates the SRP (discussed later). Break the method into two: one returns the value, and the other changes the state.

Preserve Whole Object/ Replace Parameter with Method You get values from an object and use them as parameters to a method call. Why not simply pass the object to the method and let it get its own values? (You can even create a parameter object to do this.) If you call a method to get a value to pass as a parameter to a second method, why not let the second method get the parameter?

Replace Constructor with Factory Method You find you need to do more than simple construction when you create an object. Make the constructor private and replace it with a factory method. Factory methods are often static methods that do a smart construction. See the Singleton pattern for an example.

Generalization These refactorings clean up inheritance hierarchies. They also allow you to ‘evolve’ the hierarchy. Template methods are methods that call private methods that can be subclassed to replace multiple methods with the same signature. Sometimes delegation works better than inheritance or vice versa, so don’t be afraid to try it both ways.

Pull Up/Push Down Field/Method These refactorings move fields and methods within an inheritance hierarchy to improve the structure and eliminate duplication. You may need to rename related fields or methods to do this when they have acquired different names during development. Take the method or field code, copy it to the new location, and remove it from the old.

Pull Up Constructor Body You have constructors on subclasses that are mostly identical. You can’t use Pull Up Method because constructors aren’t inherited. 8) Create a superclass constructor containing the common code and call this from the subclass methods using super(args).

Extract Subclass/ Superclass/Interface When a class has features that are used only in certain cases, give those features to subclasses. This is similar to Extract Class using delegation. Extract Subclass is usually simpler but more limited than Extract Class.Extract Class Push down the methods first and later the fields. Watch for fields that you can throw away. You can also use this to define a ‘null object’. Extract Superclass is the reverse process. Extract Interface creates an interface the same way.

Collapse Hierarchy After a while, a class hierarchy grows complex. If you refactor it a bit, moving fields and methods around and extracting classes and interfaces, you may discover that some classes no longer do anything useful. Get rid of them. Choose a class to sacrifice, move its remaining fields and methods, and kill it. Don’t get blood on your clothes.

Form Template Method You have two methods associated with sibling subclasses that perform similar operations in the same order, but the operations are not the same. Exploit polymorphism. Extract the operations into methods with the same signature (names and argument lists), so that the original methods become the same. You may need to rename one. Then you can pull the original methods up into a superclass, and the differences live in the subclasses.

Replace Inheritance with Delegation (and vice versa) See the discussion of Extract Class versus Extract Subclass.Extract Class Extract Subclass A subclass only uses part of a superclass interface or doesn’t use inherited data. Change the subclass to a separate class and delegate. Or the reverse… Whatever works.

Big Refactorings Tease Apart Inheritance Convert Procedural Design to Objects Separate Domain from Presentation Extract Hierarchy

Tease Apart Inheritance Your design was by a C++ programmer who believed in multiple inheritance. 8( Create two hierarchies from the complex one and use delegation to invoke one from the other. –The more important of the two responsibilities should define inheritance in the original tree. –The lesser responsibility should have its own tree. –Link them at the hip (abstract base class to abstract base class) so that to the outside it looks like a single complex hierarchy. –You may need to Replace Constructor with Factory Method.Replace Constructor with Factory Method

Convert Procedural Design to Objects Someone who never took CSE301 did an OO design. It looks like a C program 8(. –Turn data into objects. Each record type should become a dumb data object with get and set operations. –Take all the procedural code and give it to a main class (creating a big heap of powerful and fertile material, aka BS). –Break up the main class behavior (using a shovel and Extract Method).Extract Method –Move the behavior into the objects (using a rake and Move Method).Move Method –Finally delete the original main class, flush it down the sewer, and celebrate with a beer.

Separate Domain from Presentation Someone who never took CSE301 designed a GUI program 8(. –Create a domain class for each window. –If the data on a window forms a grid, create classes for each row and a collection to hold the rows. –Separate the presentation from the domain using Move Field and Duplicate Observed Data.Move Field Duplicate Observed Data –Use Extract Method and Move Method to do the same for behavior.Extract Method Move Method –Refactor the resulting mess mercilessly to clean up.

Extract Hierarchy You have a class that has a zillion special cases since the designer never heard of the SRP or polymorphism 8(. Make a list of important special cases. Extend it as you learn more. Take your time to get it right. –Create a subclass for each special case. –Use Replace Constructor with Factory Method to produce the subclasses.Replace Constructor with Factory Method –Methods with conditional logic should Replace Conditional with Polymorphism or Extract Method.Replace Conditional with Polymorphism Extract Method –Refactor mercilessly to clean up.

Beck’s Comments on Putting it all Together Even if you know the refactorings, you may not know when to do it. Beck claims there is a rhythm to refactoring. Practice it. You’re getting it when you start to feel confident that you can take anything that has been screwed up and make it better. You’re getting it when you can ‘stop with confidence.’ You’ve done enough. If the code is better, release it. If not, flush it.

The Feeling You Want You have a different relationship with your program. The design is fluid and plastic and under your control. It changes and adapts to changes in your requirements. You can feel it.

Learning Refactoring Pick a goal—something’s wrong with the program. Resolve to fix it. Then fix it. Stop when you’re unsure. Backtrack. Use test-driven development to make sure you haven’t broken something. If you have, back up. Work with a friend. ‘We explain to each other what we don’t understand.’ You’ll learn a lot in the process.