Refactoring — From Zero to Hero

Dhurim Kelmendi
Remote Engineering Academy
8 min readJun 3, 2017
image source: Unsplash

What is it? Should we do it? When should we do it? How do we do it? The manager does not like it… Let’s talk about these issues one at a time.

Human beings are prone to mistakes. Because of that, we need a phase to review and improve our work, so that the final product is of high quality. In software engineering, this phase is called refactoring.

This article will be an explanation of refactoring in software engineering. We will be elaborating theoretical terms, and then give an example of refactoring from real-life. But, no explanation is complete without clarifying the benefits and challenges that the subject brings, so we will do that too.

Let’s get to it, shall we?

Definitions

The theoretical concepts mentioned in this article will be extracted from the real experts; Refactoring: Improving the Design of Existing Code book and several articles in the IEEE Software Magazine, Issue 6, 2016 which focuses on Refactoring.

One of the most important traits of a software product is that it is easy to upgrade in the future (maintainable). To achieve it, developers spend a lot of their time during the software process designing the system to be maintainable. But, as humans, developers are prone to mistakes. So, it is crucial that we leave some time after implementing the design (software, not graphic design) to improving the system.

“Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.”

Martin Fowler

Based on several articles from IEEE Software, we can say that refactoring is a very important phase in the software process, and a core practice in agile methodologies (read more) and especially in Extreme Programming (read more).

It is considered as an implicit component of agile development, where developers are expected to continuously improve the code quality (read more). Another case where refactoring is required is when software requirements evolve, and the developers need to adapt the system (read more).

The need to refactor

How do we now if we need to refactor? We determine the need for refactoring based on code smells, which are best described by this quote:

“If it stinks, change it.”

— Grandma Beck, discussing child-rearing philosophy

Let’s see some of the code smells that Martin Fowler, Kent Beck and other authors of the book Refactoring give us:

  • Duplicate Code

As the name suggests, this is the case when you end up with the same piece of code in several places. That is duplicate code. This can be fixed by extracting the code and turning it into a method, and then calling that method instead of copy-pasting the code. This solution is known as Extract Method.

  • Long Method

In this case, we have a long method which is composed of many implicit methods, that is, when we have many different processes being completed inside a single method. Most of the time, we can use Extract Method to, well, extract the implicit methods and make them real methods, and this way we end up with a much more decomposed method with a clearer purpose.

  • Large Class

This smell breaks the Single Responsibility Principle (SRP); the ‘S’ in the SOLID principles. This principle states that each class should only have one reason to change, which means it should only have one responsibility. And when we have a large class, that means it has more than one responsibility, which is bad, because it makes the purpose of the class unclear. To follow the SRP, we use the Extract Class, where one class plays the role of two classes, or Extract Subclass, where a class has features that are used only in some instances.

There are more code smells, and if you are interested, we definitely recommend the Refactoring book.

But, should you refactor every time you encounter code smells? Here is what Martin Fowler tells us:

Smells don’t always indicate a problem. Some long methods are just fine. You have to look deeper to see if there is an underlying problem there — smells aren’t inherently bad on their own — they are often an indicator of a problem rather than the problem themselves.

— Martin Fowler

When?

Again, as most of the concepts presented in this article, we will be referring to the Refactoring book, from where we can also get the when of refactoring. The book recommends that refactoring is done continuously, in short bursts rather than specifying a certain time during the work process only for refactoring. Also, we do not decide to refactor, it comes as a result of having to do some other task.

Cases when we should refactor include:

  • The rule of three

Three strikes and you refactor. — Martin Fowler

That means, you have to refactor after you duplicate something twice, because the first time you duplicate is tolerable, but when that is repeated, this immediately shows that the duplicated code should be refactored (see above for tips on how to do it).

  • When we add a function

This is the most common case, when we have to add a new functionality to the system. Refactoring in this case helps us understand the system and the other thing is that we might not appreciate the design choices we see, so we decide to refactor; making the addition of the feature a straightforward process.

  • When we are fixing a bug

Again, refactoring in this case helps us understand the system and that helps us find the bug. Bugs are indicators that we need refactoring, because if we understood the code, we would not have introduced a bug.

  • When we are doing a code review

Instead of giving tips on how to improve the code, Martin Fowler suggests that we actually implement the changes; in other words, we refactor. This gives the code review concrete results and the proposed solutions are not abstract, rather they can be seen and examined instead of being imagined.

Benefits

Refactoring does not fix every defect in software, but it definitely helps improve many aspects of the software.

  • Improves the system design

Software, after some time, will start to decay. To avoid it, we do refactoring, as it keeps our code healthy and in good shape. Having poorly designed software may be good in the short-term, but it definitely has a long-term effect; this effect is called technical debt. Basically, it tells us that if we make cheap and quick choices instead of implementing the best practices, they will hunt us down in the future. If we take an analogy with dish washing, the technical debt would mean that we do not clean the dishes today, but leave them for tomorrow. This is not a big problem if we do it sometimes, but if we always do it, our kitchen will be a real mess, which would look something like the picture below, or worse?!

Image source: commons.wikimedia.org

Refactoring helps us clean our kitchen (analogy with software), keeping it clean and easy to work with in the future.

  • Makes the system easier to understand

Refactoring helps us understand the system, because it makes our code readable, helping others understand our code. And another way refactoring improves understandability is when we are looking at unfamiliar software. Instead of looking at the code and trying to figure out what it does, we refactor it to fit our understanding and then test it to see if we understood it correctly.

  • Makes bugs easier to be found

Logically, understanding the code makes bugs very easy to be found. So, refactoring also helps us find bugs. And, even though we might not be great at finding bugs, by having good habits as refactoring, we achieve better results.

“I’m not a great programmer; I’m just a good programmer with great habits.”— Kent Beck

  • Software development process is faster

The most important benefit of refactoring is that it speeds up the development process. Although this might sound counter-intuitive, by understanding the aforementioned concept of technical debt, this makes a lot of sense. If we wash our dishes regularly, we avoid having a large pile of dishes to wash. The same goes for our software. If we refactor all the time, we will have a very low technical debt, which implies that we will spend time on developing software rather than fixing issues introduced from poor choices in the past.

Challenges

Even though we, as developers, want to refactor, we might face a challenge: the Manager (or the Client, if you are a freelancer). Because refactoring is time-consuming, convincing the manager to include it in the development process can be a very difficult task. Martin Fowler tells us that if the manager is tech-savvy, or genuinely quality oriented, we should convince them by showing the benefits of refactoring; that it saves time and improves quality, etc.

However, if the manager is one of the people who claims to be quality oriented, but is actually schedule oriented, Martin Fowler says that we should not tell them that we will be refactoring. It is our job to develop software as fast as we can, and if we need to refactor in order to achieve that, we refactor. After all, they are schedule oriented, so time will be their most valuable asset.

Real-life example with Laravel

Tired of theory? Alright, let’s see a real-life example of refactoring. This example will show the Duplicate Code smell, and fix it as suggested above, by Extract Method. It is rather a simple example, just to show the practical aspect of some of the concepts introduced in the article.

While developing a web application using the Laravel framework of the PHP language, I needed to parse the date of many objects in many views. I was using the great Carbon library for parsing the date, but the problem was that I started duplicating the code. Here’s what the code looks like, written using Laravel Blade templates:

Then, I decided to define a helper method and, as a result, eliminate the duplicate code. I defined a parse_date method, which took two parameters, the date, and the date format.

After defining the helper method, I removed the duplicate code and just called the method instead. This improves the code quality, because if I decide to change the way I parse dates, I do not have to make changes in many places, rather I just change the method. Here’s what the code looks like after refactoring:

Although it is a small change, it makes sense to extract duplicate code into a method and call the method instead. You can go one step further, by removing the format parameter and specifying the date format inside the method, but in our case, I needed to specify different formats for different models. As you can see from this simple example, refactoring is a very domain-specific process, which means that there is not only one correct solution, it all depends on what you want to achieve.

Feel free to email me if you have any questions, challenging opportunities, or you just want to say hi.

Finally, be sure to follow me so that you do not miss any new stories I publish.

--

--

Dhurim Kelmendi
Remote Engineering Academy

Polyglot Software Engineer. I have a lot of failure and success stories, some of which I share here. I teach what I want to learn.