

By continuously improving the design of code, we make it easier and easier to work withβββJoshua Kerievsky, Refactoring toΒ Patterns
Refactoring is taking an existing, working, code, and make that code better.
Okay, but what does it mean βbetterβ? It means better structured, better built, more readable, and more understandable.
Your code is easier to work with, itβs easier to add new features, easier to spot and fix bugs, easier to extend and maintain, and itβs a way to stop your code from gradually getting out of control.
If youβve ever looked at a method that was getting a little too long, and found a few lines in it that belong together, separated those out into their own method.
And then replaced the original code with a call to that new method. Well, thatβs a refactoring, that is the extract method refactoring.
Itβs a collection of small, independent techniques for improving code that already exists. This code is already written, and itβs already working. Weβre not changing what it does.
These individual techniques, each one is a single refactoring technique, and they are often very small, and each deal with one specific common issue.
There is no such thing as a set of rules or a specific order that just anyone can follow. But there is a set of techniques to help you to refactor your code.
Now if youβve been writing code for awhile, youβve almost done some of this already. But using the formal refactoring technique, brings more conscious awareness to that decision.
It doesnβt replace your intuition, but it gives you some more questions to ask:
A useful way to think about the refactoring techniques is to understand they can be grouped into several categories based on the different levels of the code they operate on.
Some of them concerned with individual methods itself, not worrying about class hierarchies or design patterns.
Then, there are refactorings where we take a slightly higher view. Weβre still looking at the method but now being a bit more aware of our classes. Is this method in the right class?.
And, we can move up another level of abstraction, not focusing so much on the methods, but more on the communication between different classes. Is class A seem to do nothing but use class Bβs methods and properties?.
And weβre even another level up. There are techniques really shine in a object oriented application. Are the clues that we should be using more inheritance and polymorphism or indeed less inheritance and polymorphism?.
You will see several refactorings that appear to be the exact inverse of each other. One refactoring technique has the name βAdd Parameterβ, but another, is βRemove Parameterβ.
And it is, after all, perfectly understandable that the technique you need is sometimes the opposite of another one.
Refactoring is not debugging.
Your code already needs to work. Itβs not a way to find bugs, you should have fixed those as soon as they happened.
So, itβs true, during the process of refactoring you may find bugs. But the moment that you start to deal with that. You have stopped refactoring and you have started bug fixing which is a very different mindset.
Refactoring is not performance.
This is another very common misconception that we cleaning our code up and thatβs going to make it faster.
No, code performance is not the goal of refactoring nor even an expectation. But, our performance is!. Weβll be able to read the code and understand it faster. Not just individual pieces of code but the bigger application.
Refactoring is not adding features
If during this process you add a new feature, you are no longer refactoring. Because in refactoring we do not change the behavior of the code.
We might be doing a lot internally, creating new classes, moving functionality from one place to another, renaming, reorganizing. But the end result of the refactoring process doesnβt change the observable behavior of the code.
So, any end user who was using our application before would have no idea we did anything at all. We did not fix bugs, we did not make it faster, we did not add features.
So, why to do refactoring anyway?
Ok, so, refactoring is not adding features, refactoring is not finding bugs, refactoring is not about performance, but we refactor simply because we want to do those things.
Because well-structured code will make it so much easier to add new features and new capabilities. It will make it easier to start analyzing performance. So weβre refactoring to get the future roadblocks out of our way.
And we do refactoring for a reason. If no reason to refactor, then donβt do it.
If we have an application written and untouched since a long time ago. It works, itβs fast enough. Thereβs no conflict with any of their other systems and no features that need to be added.
It could be the ugliest code in the world, but, it doesnβt need to be refactored. Because it would be no reason to do so.
In the team culture, it can often be difficult for teams to get approval to spend time refactoring when itβs not part of the culture, because the benefits arenβt immediately apparent.
Yes, weβre not adding features, weβre not working on performance, weβre not fixing bugs, so why bother? We bother so we can do those things easier.
Refactoring is not an independent stage.
When you first learn about refactoring, it sounds like something you do as an independent stage. That you write an application and later you refactor it.
Well, you may need to do that from time to time if you have an existing code thatβs a mess, but, the intention is that you start to do this all the time.
That as you write code, you refactor as you go. You write a new class or some new methods, check and test it, and then take a few minutes to scan and make sure itβs refactored as it could be.
In a team environment, a great way to learn refactoring is with code reviews or paired programming.
Bringing multiple sets of eyes to the same code. You find different people spot different opportunities for refactoring.
And, if youβre a solo developer, you need to pay a little more attention to applying the individual techniques, particularly those you wouldnβt naturally think about.
We wonβt dig into each refactoring technique, whatβs the problem it tries to solve, and how to apply it in the code. Most of them are easy to understand, and you can find them in βWhere to go nextβ section below.Start with the common low level techniques, all the way up to more different levels.
First, you donβt need to know all the refactorings, just start using them.
In fact to learn them well, itβs more practical to pick just a handful set of techniques and start to actively apply those.
After learning even a few of these refactoring techniques youβll find yourself naturally writing more modular code, better object-oriented code, of knowing the correct place to put a piece of functionality or a piece of data.
So, how to start? start from the bottom, the the lower level, basic refactorings, all the way up.
Things like renaming and extracting methods, shortening parameter lists, minimizing un-useful temps, making your conditions easier to read.
So, when youβre looking at a part of the code, just scan through that part of it two or three times.
What youβre not looking for is where I can apply X refactoring technique.
What youβre looking for are the things the will bring your attention. The things that make this code smells bad. And we use it as an indicator we have something to improve. This is whatβs refereed to code smells.
So, duplicated code, a long method, long parameter lists, too many comments, and the list goes on.
But, some code smells donβt come from scanning, they will require close attention. Things like, data clumps or places to push down or pull up methods or fields.
Many of the most common programming IDEs, like Visual Studio, Xcode, and Eclipse, will actually help you do many of these refactoring techniques.
Weβre changing code and that brings risk.
The single best way to prove that the changes you make when refactoring only do what you intend is to have a set of automated unit tests you can run on your code before and after.
Automated testing can be done using a test framework like Jnit in Java.
Automated testing all the way to test driven development or behavior driven development strategies are extremely complementary to refactoring.
When youβre comfortable with a set of refactorings and you want to take it further and explore more, then your resources should absolutely include βRefactoring Improving the Design of Existing Codeβ, by Martin Fowler.
This book isnβt intended to be read from cover to cover. Most of it is a catalog of refactorings. So itβs more of a reference than tutorial.
The refactoring.com (associated with martin fowlerβs book) and refactoring.guru websites have short summaries, with code examples.
And as you get more comfortable, you may also want to look for resources on refactoring in your platform or environment. The principles are exactly the same. But there are often platform specific tips and tricks.
Thanks for reading! If you enjoyed this article, would you give me a few claps by clicking the π button? It helps aΒ lot!
Create your free account to unlock your custom reading experience.