Refactoring in Agile:
How To Make Design Changes Safely and Effectively
Agile 101
As a software development manager you just inherited a large codebase and everyone is expecting you to come up with crucial new features.
Preferably yesterday.
You’d love to do it. But neither you nor your team understands the code. Could code refactoring help you? Code refactoring in agile is hot after all. You hear it’s what keeps teams able to respond to change quickly.
And that’s exactly what you need.
But neither you nor your team have experience with it. You’re looking to get a good start, to understand the fundamentals and receive guidance on how to practice it.
Well, you’re in the right place.
This article will equip you with the right basics, so you’ll soon be well on your way refactoring the existing code base and adding new features.
Brief Overview
Over time, software design tends to degrade, and systems become increasingly difficult to change.
Code refactoring aims to keep software from degrading, or, when it’s already degraded, to improve its design so it becomes easier to understand and change.
Code refactoring is important to eliminate design flaws, achieve maintainability, and extensibility of a software system.
Crucially, code refactoring changes the design of the code, but never the behavior of the software. Never the twain shall mix.
Brief History: The Birth of Refactoring
Refactoring wasn’t a happy accident.
Programmers have been instinctively cleaning up, reorganizing, and restructuring their code since the first programs were written.
Then, In the late 1980s, two computer science graduate students at the time (William Opdyke at the University of Illinois at Urbana-Champaign and William Griswold at the University of Washington), independently invented what’s now called software refactoring.
Here’s a brief evolution of refactoring:
Here’s a brief evolution of refactoring:
Researcher | William Griswold -Young graduate student of Computer Science -Relatively inexperienced in working outside the academia -1985-86: Began doctoral program at University of Washington and started working with David Notkin | William Opdyke -Computer Science student -Software development experience at Bell Labs involving hundreds or thousands of staff, supporting products with lifetimes of 10 to 20 years or more. -1988: Began doctoral program at the University of Illinois at Urbana-Champaign |
Focus of Research | -Software Evolution Once applications were deployed, they could no longer be altered. | Software Change Including knowledge-based software engineering, program transformation, and database schema evolution. |
Early Influencer(s) | 1987: -Tony Hoare and his colleague’s Article: Laws of programming. -Key principle: Algebraically transform one design of a program into any other possible design. 1988: -Notkin’s proposal: Restructure programs to improve their design. -Griswold extended Notkin’s proposal that restructurings should be meaning-preserving. | 1986: -Fred Brooks’ Article – No Silver Bullet -Shared the key idea: “Grow—don’t build—software” – Ralph Johnson’s course in object-oriented programming promotes reusability and the idea to improve the design of code. -Other key influencers: a research team at Tektronix that included Kent Beck, Ward Cunningham, and Rebecca Wirfs-Brock. 1990: -Opdyke and Johnson authored “Refactoring: An Aid in Designing Application Frameworks and Evaluating Object-Oriented Systems.” |
Key Driver | -How to build a tool to support meaning-preserving restructuring? | -How to program restructuring operations (refactorings) that support the design, evolution, and reuse of object-oriented application frameworks. |
Key Contributions | 1991: -Griswold completed his dissertation.Command-line tool automated a modest catalog of meaning-preserving -transformations.Demonstrated that you can carry out a sophisticated rearchitecting of an application using just meaning-preserving transformations. | 1992: -Opdyke completed his dissertation. -What refactorings should you apply in a given situation? -How, if at all, can you safely refactor in a given situation? -Demonstrated how you could achieve significant functional changes and system-level design improvements by composing a series of more primitive changes. -Opdyke introduced Martin Fowler to his refactoring research. |
Unique Contributions | Focused on the meaning-preserving aspects of refactoring. | -Focused on the unique opportunities in refactoring object-oriented programs. |
How Does It Work
What is Refactoring?
Refactoring code is changing code with two crucial constraints:
- The changes make the code easier to understand and thus cheaper to modify.
- The changes never change the functionality, the observable behavior, of the code.
That second constraint bears repeating: a refactoring should never change the behavior of a program. This means that if the program is called before and after a refactoring with the same set of inputs, the resulting set of output values will be the same.
You’ll also hear refactoring used as a noun and a verb. And here’s a quick definition.
Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.
Refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behavior.
Why Should You Refactor?
If the code works, isn’t refactoring gold plating? A waste of time? A mental exercise to keep up your billing by the hour? Entertaining yourselves as you try and make your code the best from some purist standpoint, or is there real value in doing it?
It turns out that refactoring is how you improve the design and quality of your code. And if you stop working on your code as soon as it seems to work, it’s very likely that it is not well suited to future changes. And thus, future changes will be more expensive.
Without proper care, the cost of changing an application can increase exponentially in proportion to its size and complexity. Eventually, it may no longer be cost-effective to update the application further.
Refactoring helps ensure that your released code is easy to maintain. As the saying goes — A stitch in time saves nine, timely refactoring makes it easy and inexpensive to incorporate new functionality.
When Should You Refactor?
If your system has much technical debt, should you stop working on new features and spend a few weeks refactoring? Sometimes this can make sense, but there are certain problems with this strategy.
Let us illustrate this with an analogy:
Imagine that you’re a chef in a fancy restaurant. You’ve been in business for six months, and you’ve established some regular customers. Things have been pretty busy, however, and you let cleaning slip. The state of your kitchen and your pots and pans interferes with your ability to deliver good-tasting meals before your guests get impatient and leave.
After a few close calls and a visit from the health inspector, it’s time that you debugged the kitchen, as it were. But you can’t just shut down your restaurant for a few weeks while you get everything cleaned up, can you? Your regulars might tolerate it, but it’s not guaranteed and you’ll definitely lose a lot of business from casual passers-by.
The same applies to software development.
Shutting down operations, the creation of value with new or improved features, is unlikely to go well with your client, stakeholders, and managers.
Good restaurants don’t operate like this. They don’t let cleanliness issues go unchecked to the point where they need to shut down. Note that I said good restaurants. They make cleanliness and maintenance a regular part of their ongoing operations.
And, again, the same applies to software development.
Regular code refactoring is like cleaning your kitchen. It’s far more effective in keeping you able to respond to new requirements and delivering value to your users or customers.
When Not to Refactor?
There are times when you shouldn’t refactor.
Refactoring should never change the behavior of the code.
This means you need to be able to verify the behavior of your code. All of your code, not just the bits you’ve changed.
Therefore you can’t, and don’t even want to refactor, when:
The ABCs of Code Smells
Kent Beck coined the term code smells in the 1990s. Code smells are symptoms, or signs, in a program’s source code that indicate a potentially deeper problem.
In his seminal book “Refactoring,” Martin Fowler gives a similar definition: “A code smell is a surface sign that usually corresponds to a deeper problem in the system.”
Code smells are not bugs.
The code is correct and the program functions as it should.
Instead, they show weaknesses in code design that may slow down development or increase the risk of bugs or failures in the future.
An example of a code smell is “Duplicate Code”: the same code copy-pasted in multiple places. It’s just a matter of time before someone forgets to change one of those copies along with its brethren.
The refactoring to apply to deodorize this smell is “Extract Method”: merging the copies into a function or a class method.
Because code smells are “problems waiting to happen” it’s good to strive for zero code smells.
The Process of Refactoring
To minimize the likelihood that you’ll accidentally introduce bugs as part of your refactoring, you want to follow a strict process.
- Ensure you can back out — restore to a version that was proven to work correctly. Make sure you’ve committed all your changes and all tests against the committed code succeed. This way you can restore back to this point if your refactoring doesn’t go as you envisioned.
- Identify what you want to refactor and how — which refactorings to use.
- If you have multiple refactorings to execute to accomplish a bigger restructure, you can optionally, select a subset of automated tests to verify unchanged behavior after each individual refactoring.
- Iteratively: apply a refactoring and verify behavior is unchanged. If the tests show you did change the behavior, change the code, never the tests.
- If you used a subset of automated tests during the refactoring process, run all tests to verify unchanged behavior for the whole application.
- Here again, if something broke, change the code to make the tests pass — don’t change the tests.
- If you realize that you’re just not going to be able to get the tests passing again in a reasonable amount of time, restore back to the working code you had before the refactoring process.
- Assess the effect of the refactorings on quality characteristics of the software (e.g., complexity, understandability, maintainability) or the process (e.g., productivity, cost, effort).
- If they’re not satisfactory and can’t easily be improved, restore back to the working code you had before the refactoring process.
Why is Refactoring Considered Dangerous?
It isn’t. I’ve never heard that it is dangerous.
Refactoring is no more dangerous than any other coding practice, really. You have to be aware of what can go wrong and take steps to avoid it.
A Quick Example: Extract Method Problem
You have a code fragment that can be grouped together.
————————————————–
void PrintOwing()
{
this.PrintBanner();
// Print details.
Console.WriteLine(“name: ” + this.name);
Console.WriteLine(“amount:”+ this.GetOutstanding());
}
————————————————–
Solution
Move this code to a separate new method (or function) and replace the old code with a call to the method.
————————————————–
void PrintOwing()
{
this.PrintBanner();
this.PrintDetails();
}
void PrintDetails()
{
Console.WriteLine(“name: ” + this.name);
Console.WriteLine(“amount: ” + this.GetOutstanding());
}
————————————————–
Why Refactor
Benefits of Refactoring
Further Reading
- W.F. Opdyke and R.E. Johnson, “Refactoring: An Aid in Designing Application Frameworks and Evolving Object-Oriented Systems,” Proc. 1990 Symp. Object-Oriented Programming Emphasizing Practical Applications (SOOPPA 90), 1990, pp. 274–282.
- W.G. Griswold and D. Notkin, “Automated Assistance for Program Restructuring,” ACM Trans. Software Eng. Methodology, vol. 2, no. 3, 1993, pp. 228–269.
- W.G. Griswold and D. Notkin, “Architectural Tradeoffs for a Meaning-Preserving Program Restructuring Tool,” IEEE Trans. Software Eng., vol. 21, no. 4, 1995, pp. 275–287.
- W.F. Opdyke, “Refactoring Object-Oriented Frameworks,” PhD diss., Dept. Computer Science, Univ. of Illinois at Urbana-Champaign, 1992.
- M. Fowler et al., Refactoring: Improving the Design of Existing Code, Addison-Wesley Longman, 1999.
- K. Beck, Extreme Programming Explained: Embrace Change, Addison-Wesley Longman, 1999.
Start Refactoring
Remember that codebase that you inherited? The one that you and your team don’t understand? That had you wondering how to deliver on everyone’s expectations for new features?
You now know how to tackle that codebase with confidence.
If there are few or no tests, your first step is to create a Golden Master.
When you have that Golden Master, or if you’re lucky enough that the codebase does have good test coverage, you can proceed with refactoring to make adding new features easier, and with adding those new features. All without closing for business!
So, go, start refactoring and adding the features everyone is waiting for.
Speed up your Agile planning and execution!
Signup for a FREE Trial of Nimble Agile