The "bible" of refactoring is Fowler's book, Refactoring. It is a very well-written book which I would have made a required text for the course if it didn't cost $50.

Refactoring by Example

We spent a whole lecture working through the example of Refactoring Chapter 1.

Foundations of Refactoring

Here are the key points of Fowler chapter 2.

Why Refactor?

When to Refactor? Everyone has a different design methodology that requires more or less refactoring.
Shortcomings with Refactoring
Refactoring and Design

Testing and Refactoring

Unit testing is critical to refactoring. Fowler chapter 4 covers JUnit, the unit testing framework. We covered this in the implementation lecture.

Here is the sequence of events to follow to test in the context of a refactoring:

If you have a series of refactorings in mind, re-test between each change.

Bad Smells in Code

See Fowler Chapter 3.

Bad Smells and refactorings to clean them up. (We are not going to delve into the proposed refactorings below in detail, but the names should give the idea.)

  1. Duplicated Code
    --extract out the common bits into their own method (extract method) if code is in same class
    --if two classes duplicate code, consider extract class to create a new class to hold the shared functionality.
  2. Long Methods
    --extract method!
  3. Long Parameter List
    --replace parameter with method (receiver explicitly asks sender for data via sender getter method)
    Example: day month, year, hour minute second ==> date
  4. Divergent Change
    If you have a fixed class that does distinctly different things consider separating out the varying code into varying classes (extract class) that either subclass or are contained by the non-varying class.
  5. Shotgun Surgery
    The smell: a change in one class repeatedly requires little changes in a bunch of other classes.
    --try to move method and move field to get all the bits into one class since they are obviously highly dependent.
  6. Feature Envy
    Method in one class uses lots of pieces from another class.
    --move method to move it to the other class.
  7. Data Clumps
    Data that's always hanging with each other (e.g. name street zip).
    --Extract out a class (extract class) for the data. Will help trim argument lists too since name street zip now passed as one address object.
  8. Switch (case) statements
    --Use inheritance and polymorphism instead (example of this was in Fowler Chapter 1; this is one of the more difficult refactorings)
  9. Lazy Class
    Class doesn't seem to be doing anything. Get rid of it!
  10. Speculative generality
    Class designed to do something in the future but never ends up doing it. Thinking too far ahead. Or you though you needed this generality but you didn't.
    --like above, collapse hierarchy or inline class
  11. Message chains
    Say you want to send a message to object D in class A but you have to go through B to get C and C to get D.
    --use hide delagate to hide C and D in B, and add a method to B that does what A wanted to do with D.
  12. Inappropriate Intimacy
    Directly getting in and munging with the internals of another class.
    --To fix this, move methods, inline methods, to consolidate the intimate bits.
  13. Incomplete Library Class
    If method missing from library, and we can't change the library, so either:
  14. Data Class
    We have already talked about this extensively: in data-centric design, there are some data classes which are pretty much structs: no interesting methods.
    --first don't let other directly get and set fields (make them private) and don't have setter for things outsiders shouldn't change
    --look who uses the data and how they use it and move some of that code to the data class via a combination of extract method and move method (see the Fowler chapter 1 example for several examples of this)
    Comments in the middle of methods are deodorant. You should really refactor so each comment block is its own method. Do extract method.
Last modified: Fri Nov 8 23:06:05 EST 2002