In part I of our refactoring series we talked about what is code refactoring, and why it deserves an investment during development. Part II was all about when to choose to refactor, what situations it's absolutely crucial to refactor in, and our teams take on the clean code approach.
Part III will highlight consideration points and risks before you start refactoring and techniques to ensure you've got refactoring down.
Make sure to come back every Wednesday for more tech shorts, how-tos, and deep dives into engineering tools and processes.
A Warning Before Refactoring
As with pretty much everything in coding, refactoring has its own risks. Even doing nothing at all comes with risks. The process of writing code involves humans, who are prone to error, even on their best days. Unintentional bugs may be introduced into the code, causing considerable performance problems. For this reason, it is essential that refactoring is done by someone who has a strong understanding of the code they’re working with. It can’t be just anyone.
Various Refactoring Techniques
In addition to understanding the original code quite deeply, it’s important that your developers understand the different refactoring methods available so they can pick the right route for moving ahead.
1. Red… Green… Refactor!
This technique has three basic steps and is a key to the agile “test-driven development” (TDD) methodology:
- Red—The first step is to write a test before writing the code to implement the feature. Starting with a test, you then write code to fail (yes, fail) the test. This helps you more clearly define the feature before the production code develops. The growth and learning are in the failure, and it generally leads to cleaner, higher-quality code.
- Green—After compiling the failures, write implementation code that passes the tests.
- Refactor—Once you have test-passing code, you can clean it, refine it and improve each piece of functionality.
The benefit of this technique is that it turns out very high-quality code in the end. While running through the red phase takes some time, it actually saves time later because “red” code options are discarded early and “green” code is then optimized.
2. Refactoring by Abstraction
Refactoring by abstraction is a method used by developers who need to change large blocks of code in a gradual fashion. The abstraction method primarily focuses on hierarchy, class inheritances, and extraction. The main goal behind this method is to eliminate messy duplications of code. Although there are a few different ways to use abstraction, the pull-up and push-down methods are the most common. The pull-up style brings code up from a subclass to a superclass. On the flip side, the push-down method takes code from the superclass and moves it down into a subclass.
3. Simplifying Methods
Paring down and simplifying the code logic is the target of these methods. Some simplifying methods revamp interactions between classes, removing, adding, and replacing particular parameters with more explicit methods.
Streamlining and removing unnecessary duplications in the code can also be accomplished through composing, which has two primary techniques:
Extraction—Breaking pieces of code into smaller bits in order to find and remove fragmentation. Developers move fragmented code and replace it with code that conforms to the new method.
Here's an example of extraction in C#:
Inline Refactoring—Simplifying and streamlining code this way involves removing obsolete methods from standing code and replacing them with content from the new method.
Here's an example of inline in C# -
The goal here is to decrease complexity and bolster code reliability and readability. Fragments or blocks of code are removed from their current methods and placed into new methods. The key is that the new methods need to be clearly labeled in a way that makes their functions very clear.
Martin Fowler in his book Refactoring: Improving the Design of Existing Code, points out how a developer does his part in reducing future technical debt. When a developer notices the need for refactoring while adding in a new feature and cleans it up, he's making it part of a software update as opposed to a seperate refactoring process. Fowler goes through an example of preparatory refactoring here.
Jessica Kerr provides a great illustrative explanation for preparatory refactoring:
"It’s like I want to go 100 miles east but instead of just traipsing through the woods, I’m going to drive 20 miles north to the highway and then I’m going to go 100 miles east at three times the speed I could have if I just went straight there. When people are pushing you to just go straight there, sometimes you need to say, “Wait, I need to check the map and find the quickest route.” The preparatory refactoring does that for me.
The Benefits of Code Refactoring
Code refactoring can seem a little like cleaning out the refrigerator. It can take time, and you might wonder if some other activity would be more productive. It’s not a glorious undertaking, but it is necessary. Code, just like old guacamole, can start to get funky and malfunction, which can cost a lot of time and resources to fix. So, although the business benefits may not be immediately obvious, the long-term benefits of refactoring are clear:
- Cleaner, simplified code is so much easier to work with, improve and update. The stability of clean code enables developers to add more functionality without damaging current functionality for end-users.
- Wise code refactoring saves money and reduces the burden on customer support resources. Clean code requires less maintenance and repair. Streamlined code causes you and your customers a lot less stress. You can use your resources to develop new functionality and solutions.
- Code refactoring improves security. Fewer bugs and vulnerabilities keep your systems safer from bad actors.
- Clean code sets you up for the future. It’s simpler for newer developers to understand, and it’s more able to adapt to new market forces that are always changing.
- Code that has been streamlined through refactoring is easier to scale as necessary and removes obstacles created by dirty, clunky code. It makes you more agile, flexible, and able to move on to future possibilities.
Are you considering a code refactoring method or want to know more about how refactoring works? Our team has explored and tested the ins and outs of different methods, and we have a lot of advice and expertise in the field. Reach out to us and we will be glad to share our insights and help you on your way.
Check back every Wednesday for more content.
A few useful resources:
- Martin Fowlers refactoring catalog with examples
- Fowler Preparatory Refactoring Example
- Uncle Bob's Clean Code: Handbook of Agile Software Craftsmanship
- Refactoring Essentials for Visual Studio on Git
- A Ruby library for carefully refactoring critical paths
- Refactoring catalog
- Visual Studio source code refactoring
- Refactoring extensions
- Fowler "Workflows of Refactoring"