5 easy wins to refactor even the ugliest code
Tags: javascript, typescript, refactorit, codenewbie
Published: 2019-08-03 19:43:15


Writing clean code can be a challenge when you start on a new project. Trying to clean up code in an already existing application without breaking anything is similar to this:

{% twitter 1150950714090278916 %}


I have been a technical lead for a few years and during that time I have seen my fair share of spaghetti code that I had to maintain, or worst extend. Through many painstakingly frustrating hours, and a dozen rubber ducks or so I have developed a few tips and tricks to help refactor even the ugliest code bases.

I put together a list of 5 quick wins that you can either apply to any code base or keep in mind if you're starting a new project.

Each win will start with a bad code sample followed by a good one with an explanation of what changed.

## 1) No Invariant Methods
A method can be considered pretty much useless if it always returns the exact same thing no matter what is passed in.
As you can see in the example invariant-method-bad.ts, getName will always return the exact same "NO NAME FOUND" message.
We fix this in the invariant-method-good.ts method by simply returning the result that we intended to from the get go.

{% gist https://gist.github.com/mlevkovsky/2c8e972972fed8ac1d908668e5ee0b7f %}


![me during code reviews](https://thepracticaldev.s3.amazonaws.com/i/7i6ugvxnxpu1yvya6rfj.jpg "me during code reviews")

## 2) No magic numbers or strings
Magic numbers and strings are hardcoded values that you can find sprinkled throughout your code. If not done carefully you will end up repeating the exact same values across your entire code base, which will make changing your code, debugging and testing it a nightmare.
As you can see below in magic-strings-bad.ts we have a hardcoded string in our method. In the file right below it, magic-strings-good.ts, we fixed this issue by refactoring it to a private read only class variable.

{% gist https://gist.github.com/mlevkovsky/845f572f7af6b6f71f78e16b124cdb89 %}



A good question to ask regarding magic numbers and strings, is "Where should I put them?". Here is how I decide where to put them:

1. Is the value only in one file? 👉 a constant in the top of the file
2. Is the value used across multiple files? 👉 a specific enum class that groups the constants logically
3. Is the value used when the application boots (e.g. an api url, a timeout threshold…) 👉 a properties file

### pssst I tweet about code stuff all the time. If you have questions about how to level up your dev skills give me a follow [@mlevkov](https://twitter.com/mlevkov)

## 3) Keep the default clause last
A switch statement can contain a default clause to handle unexpected value. Considering you are most likely working collaboratively on a code base, it's important to follow conventions to ease communication.
Considering the example below, just moving the default clause all the way to the bottom will already save a lot of frustration for your peers.

{% gist https://gist.github.com/mlevkovsky/4811ec0255783cda2e7fe9cd0c82d9ba %}



## 4) Clean up your redundant variables
Keep an eye out when you don't need to instantiate a variable at all. Redundant variables take up memory, clutter up your code, make it harder to debug and add new features. Try to keep your code as tidy as possible. In the examples below, it's painfully obvious we don't need to create an instance of a BackgroundImage each time, and can just assign the value for each case.

{% gist https://gist.github.com/mlevkovsky/17a768152f2ca13962fab1c1a05a13b9 %}



## 5) Forget the else, return if you can
An important concept in keeping code clean is cyclomatic complexity. Cyclomatic complexity is basically how many loops, conditionals or function calls do you have nested in our code. Really high cyclomatic complexity makes code nearly impossible to wrap your head around. You will definitely need a dozen rubber ducks if it gets out of control.
Let's simplify the example from above by going from a switch statement to a tidy series of ifs.

{% gist https://gist.github.com/mlevkovsky/7a6ad06b3b18bbd07758a42ca121c23d %}



This last example keeps the flow of logic dead simple. There is no alternative flows that you have to map out, everything is very straight forward and becomes much easier to digest.

There you have it, 5 easy tips that you can apply to almost any codebase.

If you want to level up your coding skills, I'm putting together a playbook that includes:

1. 30+ common code smells & how to fix them

1. 15+ design pattern practices & how to apply them

1. 20+ common JS bugs & how to prevent them

Get early access to the [Javascript playbook](https://javascriptplaybook.com/).