Less noise, more data. Get the biggest data report on software developer careers in South Africa.

Dev Report mobile

How I Used Clean Code to Fix an Unnatural Solution

20 July 2022 , by Carlos Limonggi

As a newly-joined front-end developer, I was assigned a project that had already been delivered to a client who had accepted an ā€œunnaturalā€ solution. I used clean coding principles to naturalise the solution, which became a model for future projects at the company. These are the principles I used and the process I followed to implement them.

Dog cleaning a text editor with soap

I was handed an assignment that was a very complex piece of code, with hundreds of lines across at least seven different files. It had a messy codebase that was the result of work from at least six previous developers.

The problem with the unnatural solution

The unnatural solution meant the client could use a feature, but it violated fundamental UX design principles. The user was forced to overthink since its behaviour was completely opposite to the real world. It was a traditional whiteboard addition operation in which the user was instructed to accept the result first rather than at the end:

Screenshot-2022-07-20-at-16.24.21

This was unnatural because the total should appear below rather than above the operation. The unnatural functionality was the result of the efforts of at least six previous developers, most of them juniors without enough experience to design such a complex use case.

Looking at the code was like looking at an alphabet soup: unreadable and beyond complex.

I had no clue where to start or where to go. The one thing that was clear was that the code needed to be fixed, so I started by cleaning it. The plan was simple: No plan at all, but remove dead code as the first step!

Whatā€™s dead code?

Dead code represents unused elements, for example:

  • Functions that are only mentioned in their own definitions but nowhere else in the code
  • Code that is commented
  • Unused variables
  • Unnecessary comments

Dead code adds noise to the source code, which leads to the opposite of what weā€™re trying to achieve. The goal is to write code that is easy to read and understand.

Itā€™s important to do an extensive search through the complete application to look for unused elements before removing dead code. This way, you can be sure that removing things wonā€™t break the solution.

Removing the dead code took me a few days, and there was no short-term reward for doing it. The other options all involved starting from scratch, but this was risky because the client had already accepted the solution. There was value in the software; I just wanted to tame it.

Whatā€™s clean code?

Code that is easy to read and understand is clean code. From Clean code by Robert C. Martin, ā€˜Code is clean if it can be understood easily ā€“ by everyone on the team.ā€™ To me, this means that even people who are not used to working in the language the code is written in can still understand its functionality and read it as if it was composed of phrases in plain English.

Following his definition of clean code, Martin has several principles to follow: Four general principles divided into sub-categories related to scopes of software development. However, there is no need to learn and use them all. To keep it simple, we can apply the four general principles to any scope of software development, so there is no need to learn the big list of subcategories and principles.

The four general principles of clean coding, according to Robert C. Martin, are:

  1. Follow standard conventions
  2. Keep it simple
  3. Boy scout rule
  4. Find the root cause

Hereā€™s how I used them.

Follow standard conventions

I decided to use camel case when naming variables and focused on being consistent across the source code. I was trying to make our code readable, so naming conventions worked like grammatical rules. You can find more about standard conventions here.

In the example below, the ā€œbeforeā€ code has no naming conventions while the ā€œafterā€ code does, making it much easier to read. When trying to read the code before applying the naming conventions, we can easily see in the first line that record and source are two different words. However, in the second line, itā€™s pretty hard to notice that recorddest is the result of joining record and dest.

When adopting a naming convention, the reader can trust that words are separated using different cases, and this makes the code easier to read.

Before:

const record.source;
const recorddest;

After:

const recordSource;
const recordDest;

Standard conventions make code easier to read and save you time when writing code. Iā€™ve used camel case as my default naming convention for several years across any situation, and itā€™s become second nature to me when writing code. It feels effortless and is so rewarding because coding and reviewing are easier and quicker. Misunderstandings are also reduced and easier to spot.

Simple code isnā€™t less code

Simpler is always better. Reduce complexity as much as possible: Code should be simple to read and understand.

Simple code doesnā€™t necessarily mean short or abbreviated. Our goal is to keep it simple to read, which usually means we need to write a little more. The aim is to be more explicit and detailed, which makes the code easier to understand. This might seem unnecessary, but it is helpful to the reader.

Before:

if (record[i] < 24) {
    alert('In order to proceed..');
}

After:

const limitDate = 24;
const currentRecordDate= record[i];
const isInvalid = currentRecordDate < limitDate;
const instructions='In order to proceed..';

if (isInvalid) { 
alert(instructions);
}

In the example above, I wrote more to make the code easily readable. More detail means itā€™s easier to read and doesnā€™t need comments. All the variable names are explicitly self-defined, which isnā€™t the case with the ā€œbeforeā€ code, where the word record is so vague and generalist that it could mean anything if we compare it with the camel-cased phrase currentRecordDate.

Writing a little more to make the code easier to understand is something I still do. Recently a colleague and I were unsure of our code when programming. Because it wasnā€™t easily readable, we doubted its correctness despite it being right. A good way to test your codeā€™s simplicity is to read it aloud. If you struggle to read it, then someone else will too. Taking time to add more detail now saves you time and suffering later.

Boy scout rule: Leave the campground cleaner than you found it

For example, fix indentation even if the mess was already there. To fix several simple errors like spacing or unnecessary comments might seem like a lot, but if we fix those details once when we notice them, it will add significant value to the code structure.

Before:

if(somethingIsTrue )
 {
doSomethingElse();}

After:

if (somethingIsTrue) {
    doSomethingElse();
}

In the ā€œbeforeā€ example, after the word doSomethingElse there are several signs with no priority, order, or level of importance. Even when those signs might be super important for the code execution itself, they look misplaced. With the ā€œafterā€ example, we can see that the signs are present, and it is a lot easier to notice that there is a pattern where every closing sign naturally matches an opening sign. This helps a lot when we need to figure out their function, parity and position to simply pass through them and focus on the method that is being executed.

Always find the root cause

Always look for the root cause of a problem. If weā€™re getting the same error every time we use a method from a shared library, then it will probably be better if we change the shared library instead of changing the result every time we use it.

When I faced the source code, I felt that the root cause might be related to the dirty and unreadable code. By fixing the root cause, I was able to fix all of the user-side functionality issues.

How cleaning code helped me fix bugs

After removing the dead code, it seemed like a good idea to try to translate this code from ā€œjeringonzaā€ to English, so I started a renaming journey. I wanted to improve the code's readability later.

When renaming, I followed the first principle and defined the standards to be ruled by:

  1. camelCase
  2. long names in variables
  3. short comments
  4. functions that only did one thing

Hereā€™s an easy-to-read example of the standards and naming conventions I used:

Before:

const recordSource;

After:

const pricesList;

To the hardest ones:

Before:

function eventListener2(y, x);

After:

function addNewRow(rowObject, positionIndex);

I then followed the second and third principles in order to clean each and every line and make it more readable.

At this point, I began seeing results: The number of lines was reduced at least to half of the original code, and the variables, including the functions, were written in English. This, along with proper indentation, meant the code was finally readable!

The code being readable gave me a huge advantage since it was relatively easy to find absurd sentences in the code with phrases related to the bad output. For example, at some moment drawTotalAdditionResult(); was called before drawElementsToAddition().

Cleaning the code enabled me to solve bugs that had been in the backlog for months in just one afternoon!

How clean code makes me a better developer

I now write code thinking about a future me who will sit in front of the computer without and might not remember what seemed so obvious at the time of coding.

Spending time thinking about my code before I write it has saved me time and effort in debugging later on.

Clean code leads to clean ideas, and I would highly recommend incorporating these principles into your coding process. These principles have made me a better developer and allowed me to fix what seemed like an impossible task while adding additional value to our clients.

Resources:

My summary of Clean Code by Robert C. Martin

If you enjoyed this article, you might also like:


Carlos Limonggi is a software developer who likes writing. He finds the process of transforming an abstract idea into sharable words and phrases fascinating.

Recent posts

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.