Refactoring — Coding for Humans

The benefits of applying refactoring techniques with examples from Martin Fowler’s Refactoring catalog

Bruno Prado
Better Programming

--

The day-to-day of a developer is wrapped in a tangle of “ifs”, “elses”, and “I need it for yesterday”s.

But the reality is that we think of so many logics and write so many codes that to implement them, we often end up creating a dialect of our own that is only understood by ourselves and the compiler. In reality, they don’t even understand, but they don’t care. After all, they won’t have to apply maintenance in this code. This dialect turns out to be more advanced and complex each day and it’s amazing how we gain accents and slang as the project’s deadline squeeze our necks. The problem with dialects is that they are difficult to understand by those who aren’t close to them.

Reflect a little on the beautiful quote below.

Meal do naidheachd! Dh’fhaodadh tu eadar-theangachadh. An do dh’fheuch thu javascript a chur an seo?

Keep calm! You’re not in the wrong article. This really is about refactoring. You see how the text in Scottish Gaelic is complicated to be read and interpreted? This is exactly how a developer feels when he needs to maintain a code that only the creator and compiler are able to understand.

Want to see? Try to find out what the code snippet below is doing…

Got it? Was it difficult? Imagine having to maintain a project with at least some 1500 lines of code like that!

All code created and every program and system developed will need to be serviced at various points in its lifecycle. This is natural. It’s at this point that the way this code was written will make the difference between intuitive and quiet maintenance, and a few days tearing your hair trying to understand what’s happening. In fact, the creator of this code itself will have problems if they need to change it again after a few dozen other developed projects.

So how can you contribute to the world without that kind of problem? Is there any cake recipe?

Let’s go to the purpose of this article: refactoring techniques. They’re techniques that aim to restructure code without its inputs and outputs being changed. If a function receives a parameter of integer type and returns a string, it should continue to occur normally after this restructuring. Basically, your work will be in the body of the function, always preserving your signature.

What Can Be the Benefits of Refactoring a Code?

Among the possible benefits, we can highlight the following:

  • Favorable reading (humans need it);
  • Favorable to reuse;
  • Favorable to performance;
  • Favorable to low coupling;
  • Favorable to single responsibility.

What are the benefits of using a refactoring technique?

First of all, you don’t need to reinvent the wheel. Just use it in your favor.

Use a good example of a technique that preferably has been created by someone who knows very well what they’re doing and who has the credibility to talk about it.

Me? No, not at all!

I’m talking about Martin Fowler, who without a doubt is someone who understands our subject very well. In this article, we will use the techniques described by him in his book Refactoring. The complete catalog containing all the techniques described is publicly available on the web, so get to work!

Analyzing a Code Snippet and Applying Refactoring Techniques

Let’s analyze some code snippets in two scenarios: before (identifying problem points) and after the application of a refactoring technique, highlighting the improvements with the technique. We’ll use some code snippets written in JavaScript. Because it’s a language that is not strongly “typed”, it becomes very prone to unintelligible codes for those who did not write them. Of course, languages typed as java or C# do not escape this problem and all the techniques demonstrated here can be applied.

Let’s take the following code snippet as a case study:

When analyzing this small function, there immediately arise some doubts. Some of them are:

  • What is the content of “list”?
  • What does this code refer to?
  • What is x?
  • What does the “find” function locate?

By applying some refactoring techniques from Martin Fowler’s Refactoring book catalog, we can eliminate each of these doubts by keeping this code more intuitive and without the need to guess or use the infamous CTRL + F.

So, let’s go step by step applying each technique, looking at the before and after of each line of this first case study.

We’ll start with the mysterious variable x.

After applying the Rename Variable technique:

After applying the Rename Variable technique, we are able to identify at any time that the manipulated object is of type “Student”, which contains data related to this class.

So we apply the same technique to the parts of the code where this variable is referenced:

So far we have eliminated the possibility of the “What is x?” question, assigning a name that describes the type and possible content of this variable. But we still have things to improve, so let’s move on.

Now that we know the type of the object that belongs to the collection being manipulated inside of the function, we can eliminate one more doubt: “What is the content of ‘list’?” Leave its contents explicit so that the reading is sufficient for that.

Currently, our function receives a parameter named “list”.

We applied the Rename Variable technique again:

Can we improve this “code” variable too?

Now it’s easier to know the contents of this list, right? But what about the name of the function? When you invoke it, can you immediately know what it does? So far we only know that it “locates”. We can change that and eliminate the doubt: “What does the ‘find’ function locate?” since we know that it encapsulates the search for a student-type object within a list.

Currently, our function says it “locates” something … Let’s change it?

After applying the Change Function Declaration

So far, we have improved the reading of our function. Let’s see how it is so far.

We have greatly improved the code, but there are still some points to improve. The structure of this function has some problems. Let’s identify them.

  • Our conditional structure is bad, we can optimize that;
  • We are using a flag that adds complexity to the code. It will not stop the iteration within the list, which will continue until the last element is traversed. This would affect performance;
  • Our function is being responsible for more than one responsibility (in addition to finding a student in a collection, it also writes in the console), making it impossible to use it in other points of the system. Without this, extra behavior is automatically executed. Wouldn’t it be better if it just returned the student from the list so that the client function can decide what to do with that return? So we favor the reuse of this code.

Again we will use the techniques of the catalog to restructure our code and thus correct those points.

After applying the Consolidate Conditional Expression technique:

Obviously, the condition remains valid. The “active” property is clearly a Boolean value, so we could simplify our code even further.

Now let’s apply the technique Replace Control Flag with Break:

By applying another refactoring technique, we replace the flag with a break, which is the most appropriate statement to sort out a loop. This, in turn, “breaks” the iteration by preventing all items in the collection from being traversed even after locating the record (which would happen if we kept the flag with the if).

Now let’s solve the last problem we identified. It’s very common in both codes written with languages ​​that are strongly “typed” and languages ​​that are not like the JavaScript we use in our example.

This problem is present when we give different responsibilities to a single function. What is expected of a function called “Find Student”? We certainly don’t expect it to print values, much less send emails. We expect it to do nothing other than to locate a student. Let’s correct this point of the code.

After applying the Extract Function:

Notice that now we return the student object to the client function. We no longer need to use the break statement “return”, which already interrupts the iteration in the way we want. This way the customer can define what he will do with the returned data.

Here’s an example of a function that would coordinate a process in which a student is obtained by the code and its name is printed on the console:

Now, here’s a client function that will use our refactored function to add a student to a new class.

It’s clear that the client can coordinate the process in the way that it needs, since using the “findStudent” function will not have any behavior beyond what is expected.

We have been able to refactor many points of our small function using the refactoring techniques proposed by Martin Fowler in the catalog of his book Refactoring. Of course, we’ve applied only a few techniques compared to what’s available in the catalog, but you already have a clear idea of the effectiveness and benefits of using such techniques.

Let’s now compare our functions, so that we can see the improvements from before and after the refactoring.

Before

After

Conclusion

Now our code is reusable, with improved performance and encouraged understanding of its content and responsibility through reading. We have also been able to reduce the number of lines of code by almost half, but while this is what matters to many, the benefits of refactoring go far beyond simply reducing lines of code.

Legibility, performance, reusability, and accountability are far more important. Sometimes, we even need to increase the number of lines of code to achieve those ideals. It is a scale that needs to be considered all the time.

So just program it anyway and then apply the refactoring techniques?

Never! The fact that you need to refactor already shows that you know how this code should have been written since birth. Programming while keeping this structure is very important and reduces the number of points that will require refactoring.

Of course, we know that day by day, with tight deadlines and its leader charging, you end up creating a code that is very prone to need a good refactoring. You need to promise yourself that you will review this code soon after delivery, and … forget it forever.

The important thing is to know that the techniques are available to be used as soon as you need them, and so you know how to avoid the need to use them in the future.

So? Let’s refactor that monolith that you left in the code making a ugly face for you? These techniques that we apply and many others are part of the catalog of the book Refactoring by Martin Fowler that can be accessed on the official website.

By the way, do you remember our first super-strange function with which we started our article?

This function only writes “Hello World” on the screen.

Remember, in addition to being a developer, you are also a writer, and your readers need to take pleasure in reading what you write.

Favorability to a single responsibility.

Thanks for reading this article.

--

--