
Refactoring
by Martin Fowler · Published 1999
Software can evolve safely by continuously improving its internal structure without changing its external behavior.
What works
- Foundational software engineering work.
- Extremely practical.
- Strong connection between design and maintainability.
- Useful across programming languages.
What doesn't
- Requires programming experience.
- Some examples reflect older coding styles.
- Refactoring becomes difficult without tests and good architecture.
Summary
Martin Fowler opens Refactoring with a precise definition the whole book revolves around: a disciplined technique for improving the internal structure of existing code without changing its external behaviour. The emphasis is on two words — "disciplined" and "without changing behaviour" — refactoring is not rewriting code from scratch, and it's not adding a new feature; it's a series of small, reversible transformations that make code more readable and flexible, while at every step you can verify its behaviour hasn't changed.
The book's central idea is that code, contrary to common belief, shouldn't be written "correctly" once and left untouched forever. Real codebases change constantly, and if their structure isn't continually improved, they gradually become brittle and frightening — a point Fowler calls "design erosion." Refactoring is the antidote to that erosion: a way for software to evolve over years without its structure collapsing.
The book is half catalogue — a precise list of named refactoring techniques, each with specific steps — and half argument: why these techniques should be learned, when to use them, and how to keep refactoring safe using automated tests.
Key ideas
1. Code smells: a vocabulary for diagnosing problems
Fowler introduces the concept of a "code smell" — recognisable signals that usually point to a deeper structural problem, even when the code appears to work. Long Method, Large Class, Duplicated Code, Primitive Obsession — these all have names, and each connects to one or more specific refactorings in the catalogue. This shared vocabulary has real practical value: a team can say in code review "this is a Feature Envy smell" and everyone immediately understands what the problem is and what the likely fix is.
2. Extract Function: the most fundamental refactoring
If one refactoring had to represent the whole book, it would be Extract Function: taking a piece of code that can be grouped together, pulling it out into a separate function, and giving it a name that says what that piece does. Fowler shows that this seemingly simple technique, applied repeatedly and consistently, turns long, incomprehensible functions into a set of small, self-explanatory ones — each small enough to understand in a few seconds.
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
3. Two hats: never refactor and add a feature at the same time
Fowler introduces the "two hats" metaphor: at any moment, you're wearing either the "adding function" hat or the "refactoring" hat — never both at once. When adding a feature, the code's behaviour should change while its structure stays untouched; when refactoring, the structure should change while behaviour stays untouched. Mixing the two makes diagnosing a new bug nearly impossible — you can't tell whether the problem came from a behaviour change or a structural one.
4. Tests as a safety net
Fowler stresses that refactoring without automated tests is a dangerous gamble — because the only way to prove "external behaviour hasn't changed" is running a trustworthy test suite repeatedly. He suggests building sufficient test coverage before starting any serious refactoring, even if that itself takes time. Without that safety net, refactoring becomes something everyone, correctly, is afraid to do.
5. The book's opening example: calculating video rental charges
Fowler builds the book's entire first chapter around a single example: a program calculating a video store's bill, factoring in rentals and customer loyalty points. He transforms this code step by step, through dozens of small, discrete refactorings, from one long, condition-heavy function into a clean set of small classes and functions — and at every step, shows exactly which named refactoring from the catalogue was applied. This example, preserved across every edition of the book, remains the most common way to teach refactoring to new programmers.
Who it's for
- Anyone maintaining an old, overgrown codebase — exactly the codebase this book was written for.
- Anyone who has read Clean Code and wants to know how to get there — this book gives the step-by-step mechanism, not just the principles.
- A team with no code review or no shared vocabulary for discussing code quality — the code smell catalogue builds a foundation for that vocabulary.
- A beginner who hasn't seen real codebases yet — without experience maintaining real code, many examples will feel abstract.
FAQ
Should I read the first or second edition?
The second, if you have the choice — JavaScript instead of Java, and more current in style. But the underlying principles are the same across both editions; the refactoring catalogue is the same catalogue, only the example language has changed.
Is refactoring always safe if I have tests?
Safer, but not absolutely safe. Tests only verify the behaviour they cover; if coverage is incomplete, refactoring can still introduce unseen bugs. Fowler recommends small, frequent refactoring steps, even with incomplete tests, as safer than large, one-off changes.
How does it differ from a "complete rewrite"?
A complete rewrite means throwing away the old code and building from scratch — high risk, high cost, and often never finishes. Refactoring means gradually transforming that same existing code, step by step, while the system keeps working the whole time. Fowler explicitly prefers gradual refactoring.
Why is the video rental example so famous?
Because it shows one real, complete example rather than scattered snippets. Watching one actual function transform from a tangled block of conditionals into clean code teaches something no abstract explanation can.
Does this book only apply to object-oriented programming?
Most of the core catalogue is built around classes and objects, but the underlying principle — small, verifiable transformation without changing behaviour — is paradigm-independent, and applies with adaptation to functional or procedural code too.
Was this useful?
Counts appear once there are 5 votes.


