"Refactoring improves through practice."

The Refactoring Workbook contains exercises to help you assess and improve your ability to refactor (Java, but close enough for C# too). It's available now from

Thanks to those who reviewed the drafts! If you like the book, please consider posting a review at Amazon or elsewhere.

Also available: Refactoring in Ruby, with Kevin Rutherford; it has its own website. We did an interview with InformIT too.

Table of Contents

Chapter 1 – Roadmap

Section 1 - Smells Within Classes
Chapter 2 – The Refactoring Cycle
Chapter 3 – Measured Smells
Interlude 1 – Smells and Refactorings

Chapter 4 – Names
Chapter 5 – Unnecessary Complexity
Interlude 2 – Inverses

Chapter 6 – Duplication
Chapter 7 – Conditional Logic
Interlude 3 – Design Patterns

Section 2 - Smells Between Classes
Chapter 8 – Data
Chapter 9 – Inheritance
Chapter 10 –Responsibility
Chapter 11 – Accommodating Change
Chapter 12 – Library Classes
Interlude 4 – Gen-A-Refactoring

Section 3 - Programs to Refactor
Chapter 13 – A Database Example
Chapter 14 – A Simple Game
Chapter 15 – Catalog
Chapter 16– Planning Game Simulator
Chapter 17– Where to Go From Here

Appendix A. Selected Answers
Appendix B. Java Refactoring Tools
Appendix C. Inverses for Refactorings
Appendix D. Key Refactorings
Inside Cover - Smells and Refactorings

Sample Chapter

Chapter 3, Measured Smells, is being hosted on my page at, and at InformIT.


"As an occasional teacher of undergraduate programming courses, I think this book is worth its weight in platinum."--Gregory Wilson, Dr. Dobb's Journal, July 2004. Page 82.


William Wake (, is a programmer, coach, and  author.

Source Code

File contains the source code for the longer examples in the book.


  • Page 63. The Elements of Programming Style is by Brian W. Kernighan and P.J. Plauger, not Kernighan and Pike. (Thanks to Mike Cohn for spotting this.)
  • Page 121. The column names in the Offering table in the diagram don't match up to the names in the code. Change the getString() calls in Offering.find() to use columns "Name" and "DaysTimes". (Thanks to Glenn Boysko and Mohsen Akhavan for spotting this.)
  • Page 197. "hadMidScore" should be "hadMidRangeScore" in the code fragment:
      boolean hadMidRangeScore = (score > 500)
    (Thanks to Marco Isella for spotting this.)

Background Reading

More Resources

Copyright 1994-2010, William C. Wake -