did-you-know? rent-now

Amazon no longer offers textbook rentals. We do!

did-you-know? rent-now

Amazon no longer offers textbook rentals. We do!

We're the #1 textbook rental company. Let us show you why.

9780201485677

Refactoring Improving the Design of Existing Code

by ; ; ; ;
  • ISBN13:

    9780201485677

  • ISBN10:

    0201485672

  • Edition: 1st
  • Format: Hardcover
  • Copyright: 1999-06-28
  • Publisher: Addison-Wesley Professional
  • View Upgraded Edition

Note: Supplemental materials are not guaranteed with Rental or Used book purchases.

Purchase Benefits

  • Free Shipping Icon Free Shipping On Orders Over $35!
    Your order must be $35 or more to qualify for free economy shipping. Bulk sales, PO's, Marketplace items, eBooks and apparel do not qualify for this offer.
  • eCampus.com Logo Get Rewarded for Ordering Your Textbooks! Enroll Now
List Price: $86.65 Save up to $21.66
  • Buy Used
    $64.99
    Add to Cart Free Shipping Icon Free Shipping

    USUALLY SHIPS IN 2-4 BUSINESS DAYS

Supplemental Materials

What is included with this book?

Summary

Once upon a time, a consultant made a visit to a development project. The consultant looked at some of the code that had been written; there was a class hierarchy at the center of the system. As he wandered through the hierarchy, the consultant saw that it was rather messy. The higher-level classes made certain assumptions about how the classes would work, assumptions that were embodied in inherited code. That code didn't suit all the subclasses, however, and was overridden quite heavily. If the superclass had been modified a little, then much less overriding would have been necessary. In other places some of the intention of the superclass had not been properly understood, and behavior present in the superclass was duplicated. In yet other places several subclasses did the same thing with code that could clearly be moved up the hierarchy.

The consultant recommended to the project management that the code be looked at and cleaned up, but the project management didn't seem enthusiastic. The code seemed to work and there were considerable schedule pressures. The managers said they would get around to it at some later point.

The consultant had also shown the programmers who had worked on the hierarchy what was going on. The programmers were keen and saw the problem. They knew that it wasn't really their fault; sometimes a new pair of eyes are needed to spot the problem. So the programmers spent a day or two cleaning up the hierarchy. When they were finished, the programmers had removed half the code in the hierarchy without reducing its functionality. They were pleased with the result and found that it became quicker and easier both to add new classes to the hierarchy and to use the classes in the rest of the system.

The project management was not pleased. Schedules were tight and there was a lot of work to do. These two programmers had spent two days doing work that had done nothing to add the many features the system had to deliver in a few months time. The old code had worked just fine. So the design was a bit more "pure" a bit more "clean." The project had to ship code that worked, not code that would please an academic. The consultant suggested that this cleaning up be done on other central parts of the system. Such an activity might halt the project for a week or two. All this activity was devoted to making the code look better, not to making it do anything that it didn't already do.

How do you feel about this story? Do you think the consultant was right to suggest further clean up? Or do you follow that old engineering adage, "if it works, don't fix it"?

I must admit to some bias here. I was that consultant. Six months later the project failed, in large part because the code was too complex to debug or to tune to acceptable performance.

The consultant Kent Beck was brought in to restart the project, an exercise that involved rewriting almost the whole system from scratch. He did several things differently, but one of the most important was to insist on continuous cleaning up of the code using refactoring. The success of this project, and role refactoring played in this success, is what inspired me to write this book, so that I could pass on the knowledge that Kent and others have learned in using refactoring to improve the quality of software.

What Is Refactoring?

Refactoring is the 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 structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written.

"Improving the design after it has been written." That's an odd turn of phrase. In our current understanding of software development we believe that we design and then we code. A good design comes first, and the coding comes second. Over time the code will be modified, and the integrity of the system, its structure according to that design, gradually fades. The code slowly sinks from engineering to hacking.

Refactoring is the opposite of this practice. With refactoring you can take a bad design, chaos even, and rework it into well-designed code. Each step is simple, even simplistic. You move a field from one class to another, pull some code out of a method to make into its own method, and push some code up or down a hierarchy. Yet the cumulative effect of these small changes can radically improve the design. It is the exact reverse of the normal notion of software decay.

With refactoring you find the balance of work changes. You find that design, rather than occurring all up front, occurs continuously during development. You learn from building the system how to improve the design. The resulting interaction leads to a program with a design that stays good as development continues.

What's in This Book?

This book is a guide to refactoring; it is written for a professional programmer. My aim is to show you how to do refactoring in a controlled and efficient manner. You will learn to refactor in such a way that you don't introduce bugs into the code but instead methodically improve the structure.

It's traditional to start books with an introduction. Although I agree with that principle, I don't find it easy to introduce refactoring with a generalized discussion or definitions. So I start with an example. Chapter 1 takes a small program with some common design flaws and refactors it into a more acceptable object-oriented program. Along the way we see both the process of refactoring and the application of several useful refactorings. This is the key chapter to read if you want to understand what refactoring really is about.

In Chapter 2 I cover more of the general principles of refactoring, some definitions, and the reasons for doing refactoring. I outline some of the problems with refactoring. In Chapter 3 Kent Beck helps me describe how to find bad smells in code and how to clean them up with refactorings. Testing plays a very important role in refactoring, so Chapter 4 describes how to build tests into code with a simple open-source Java testing framework.

The heart of the book, the catalog of refactorings, stretches from Chapter 5 through Chapter 12. This is by no means a comprehensive catalog. It is the beginning of such a catalog. It includes the refactorings that I have written down so far in my work in this field. When I want to do something, such as Replace Conditional with Polymorphism (255), the catalog reminds me how to do it in a safe, step-by-step manner. I hope this is the section of the book you'll come back to often.

In this book I describe the fruit of a lot of research done by others. The last chapters are guest chapters by some of these people. Chapter 13 is by Bill Opdyke, who describes the issues he has come across in adopting refactoring in commercial development. Chapter 14 is by Don Roberts and John Brant, who describe the true future of refactoring, automated tools. I've left the final word, Chapter 15, to the master of the art, Kent Beck.

Refactoring in Java

For all of this book I use examples in Java. Refactoring can, of course, be done with other languages, and I hope this book will be useful to those working with other languages. However, I felt it would be best to focus this book on Java because it is the language I know best. I have added occasional notes for refactoring in other languages, but I hope other people will build on this foundation with books aimed at specific languages.

To help communicate the ideas best, I have not used particularly complex areas of the Java language. So I've shied away from using inner classes, reflection, threads, and many other of Java's more powerful features. This is be

Author Biography

Martin Fowler is the Chief Scientist of ThoughtWorks, an enterprise-application development and delivery company. He's been applying object-oriented techniques to enterprise software development for over a decade. He is notorious for his work on patterns, the UML, refactoring, and agile methods. Martin lives in Melrose, Massachusetts, with his wife, Cindy, and a very strange cat. His homepage is http://martinfowler.com.

Kent Beck consistently challenges software engineering dogma, promoting ideas like patterns, test-driven development, and Extreme Programming. Currently affiliated with Three Rivers Institute and Agitar Software, he is the author of many Addison-Wesley titles.

John Brant and Don Roberts are the authors of the Refactoring Browser for Smalltalk, which is found at http://st-www.cs.uiuc.edu/~brant/RefactoringBrowser/. They are also consultants who have studied both the practical and theoretical aspects of refactoring for six years.

William Opdyke's doctoral research on refactoring object-oriented frameworks at the University of Illinois led to the first major publication on this topic. He is currently a Distinguished Member of Technical Staff at Lucent Technologies/Bell Laboratories.

John Brant and Don Roberts are the authors of the Refactoring Browser for Smalltalk, which is found at http://st-www.cs.uiuc.edu/~brant/RefactoringBrowser/. They are also consultants who have studied both the practical and theoretical aspects of refactoring for six years.



Table of Contents

Foreword xiii
Preface xv
What Is Refactoring? xvi
What's in This Book? xvii
Who Should Read This Book? xviii
Building on the Foundations Laid by Others xix
Acknowledgments xix
Refactoring, a First Example
1(52)
The Starting Point
1(6)
The First Step in Refactoring
7(1)
Decomposing and Redistributing the Statement Method
8(26)
Replacing the Conditional Logic on Price Code with Polymorphism
34(18)
Final Thoughts
52(1)
Principles in Refactoring
53(22)
Defining Refactoring
53(2)
Why Should You Refactor?
55(2)
When Should You Refactor?
57(3)
What Do I Tell My Manager?
60(2)
Problems with Refactoring
62(4)
Refactoring and Design
66(3)
Refactoring and Performance
69(2)
Where Did Refactoring Come From?
71(4)
Bad Smells in Code
75(14)
Kent Beck
Martin Fowler
Duplicated Code
76(1)
Long Method
76(2)
Large Class
78(1)
Long Parameter List
78(1)
Divergent Change
79(1)
Shotgun Surgery
80(1)
Feature Envy
80(1)
Data Clumps
81(1)
Primitive Obsession
81(1)
Switch Statements
82(1)
Parallel Inheritance Hierarchies
83(1)
Lazy Class
83(1)
Speculative Generality
83(1)
Temporary Field
84(1)
Message Chains
84(1)
Middle Man
85(1)
Inappropriate Intimacy
85(1)
Alternative Classes with Different Interfaces
85(1)
Incomplete Library Class
86(1)
Data Class
86(1)
Refused Bequest
87(1)
Comments
87(2)
Building Tests
89(14)
The Value of Self-testing Code
89(2)
The JUnit Testing Framework
91(6)
Adding More Tests
97(6)
Toward a Catalog of Refactorings
103(6)
Format of the Refactorings
103(2)
Finding References
105(1)
How Mature Are These Refactorings?
106(3)
Composing Methods
109(32)
Extract Method
110(7)
Inline Method
117(2)
Inline Temp
119(1)
Replace Temp with Query
120(4)
Introduce Explaining Variable
124(4)
Split Temporary Variable
128(3)
Remove Assignments to Parameters
131(4)
Replace Method with Method Object
135(4)
Substitute Algorithm
139(2)
Moving Features Between Objects
141(28)
Move Method
142(4)
Move Field
146(3)
Extract Class
149(5)
Inline Class
154(3)
Hide Delegate
157(3)
Remove Middle Man
160(2)
Introduce Foreign Method
162(2)
Introduce Local Extension
164(5)
Organizing Data
169(68)
Self Encapsulate Field
171(4)
Replace Data Value with Object
175(4)
Change Value to Reference
179(4)
Change Reference to Value
183(3)
Replace Array with Object
186(3)
Duplicate Observed Data
189(8)
Change Unidirectional Association to Bidirectional
197(3)
Change Bidirectional Association to Unidirectional
200(4)
Replace Magic Number with Symbolic Constant
204(2)
Encapsulate Field
206(2)
Encapsulate Collection
208(9)
Replace Record with Data Class
217(1)
Replace Type Code with Class
218(5)
Replace Type Code with Subclasses
223(4)
Replace Type Code with State/Strategy
227(5)
Replace Subclass with Fields
232(5)
Simplifying Conditional Expressions
237(34)
Decompose Conditional
238(2)
Consolidate Conditional Expression
240(3)
Consolidate Duplicate Conditional Fragments
243(2)
Remove Control Flag
245(5)
Replace Nested Conditional with Guard Clauses
250(5)
Replace Conditional with Polymorphism
255(5)
Introduce Null Object
260(7)
Introduce Assertion
267(4)
Making Method Calls Simpler
271(48)
Rename Method
273(2)
Add Parameter
275(2)
Remove Parameter
277(2)
Separate Query from Modifier
279(4)
Parameterize Method
283(2)
Replace Parameter with Explicit Methods
285(3)
Preserve Whole Object
288(4)
Replace Parameter with Method
292(3)
Introduce Parameter Object
295(5)
Remove Setting Method
300(3)
Hide Method
303(1)
Replace Constructor with Factory Method
304(4)
Encapsulate Downcast
308(2)
Replace Error Code with Exception
310(5)
Replace Exception with Test
315(4)
Dealing with Generalization
319(40)
Pull Up Field
320(2)
Pull Up Method
322(3)
Pull Up Constructor Body
325(3)
Push Down Method
328(1)
Push Down Field
329(1)
Extract Subclass
330(6)
Extract Superclass
336(5)
Extract Interface
341(3)
Collapse Hierarchy
344(1)
Form Template Method
345(7)
Replace Inheritance with Delegation
352(3)
Replace Delegation with Inheritance
355(4)
Big Refactorings
359(20)
Kent Beck
Martin Fowler
Tease Apart Inheritance
362(6)
Convert Procedural Design to Objects
368(2)
Separate Domain from Presentation
370(5)
Extract Hierarchy
375(4)
Refactoring, Reuse, and Reality
379(22)
William Opdyke
A Reality Check
380(1)
Why Are Developers Reluctant to Refactor Their Programs?
381(13)
A Reality Check (Revisited)
394(1)
Resources and References for Refactoring
394(1)
Implications Regarding Software Reuse and Technology Transfer
395(2)
A Final Note
397(1)
References
397(4)
Refactoring Tools
401(8)
Don Roberts
John Brant
Refactoring with a Tool
401(2)
Technical Criteria for a Refactoring Tool
403(2)
Practical Criteria for a Refactoring Tool
405(2)
Wrap Up
407(2)
Putting It All Together
409(4)
Kent Beck
References 413(4)
List of Soundbites 417(2)
Index 419

Supplemental Materials

What is included with this book?

The New copy of this book will include any supplemental materials advertised. Please check the title of the book to determine if it should include any access cards, study guides, lab manuals, CDs, etc.

The Used, Rental and eBook copies of this book are not guaranteed to include any supplemental materials. Typically, only the book itself is included. This is true even if the title states it includes any access cards, study guides, lab manuals, CDs, etc.

Excerpts

Once upon a time, a consultant made a visit to a development project. The consultant looked at some of the code that had been written; there was a class hierarchy at the center of the system. As he wandered through the hierarchy, the consultant saw that it was rather messy. The higher-level classes made certain assumptions about how the classes would work, assumptions that were embodied in inherited code. That code didn't suit all the subclasses, however, and was overridden quite heavily. If the superclass had been modified a little, then much less overriding would have been necessary. In other places some of the intention of the superclass had not been properly understood, and behavior present in the superclass was duplicated. In yet other places several subclasses did the same thing with code that could clearly be moved up the hierarchy. The consultant recommended to the project management that the code be looked at and cleaned up, but the project management didn't seem enthusiastic. The code seemed to work and there were considerable schedule pressures. The managers said they would get around to it at some later point. The consultant had also shown the programmers who had worked on the hierarchy what was going on. The programmers were keen and saw the problem. They knew that it wasn't really their fault; sometimes a new pair of eyes are needed to spot the problem. So the programmers spent a day or two cleaning up the hierarchy. When they were finished, the programmers had removed half the code in the hierarchy without reducing its functionality. They were pleased with the result and found that it became quicker and easier both to add new classes to the hierarchy and to use the classes in the rest of the system. The project management was not pleased. Schedules were tight and there was a lot of work to do. These two programmers had spent two days doing work that had done nothing to add the many features the system had to deliver in a few months time. The old code had worked just fine. So the design was a bit more "pure" a bit more "clean." The project had to ship code that worked, not code that would please an academic. The consultant suggested that this cleaning up be done on other central parts of the system. Such an activity might halt the project for a week or two. All this activity was devoted to making the code look better, not to making it do anything that it didn't already do. How do you feel about this story? Do you think the consultant was right to suggest further clean up? Or do you follow that old engineering adage, "if it works, don't fix it"? I must admit to some bias here. I was that consultant. Six months later the project failed, in large part because the code was too complex to debug or to tune to acceptable performance. The consultant Kent Beck was brought in to restart the project, an exercise that involved rewriting almost the whole system from scratch. He did several things differently, but one of the most important was to insist on continuous cleaning up of the code using refactoring. The success of this project, and role refactoring played in this success, is what inspired me to write this book, so that I could pass on the knowledge that Kent and others have learned in using refactoring to improve the quality of software. What Is Refactoring? Refactoring is the 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 structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence when you refactor you are improving the design of the code after it has been written. "Improving the design after it has been written." That's an odd turn of phrase. In our current understanding of software development we believe that we design and then we code. A good design comes first, and the coding comes second. Over time the code will be m

Rewards Program