loading...
Cover image for Clean up your code by applying these 7 rules ⚡️

Clean up your code by applying these 7 rules ⚡️

joachimzeelmaekers profile image Joachim Zeelmaekers ・6 min read

Readable code is maintainable code

In this short post, I will go over some of the rules that you can apply to improve your code. All code samples are Javascript.

I find that Readable code is maintainable code.
The goal for me as a developer is to write quality code. Every developer on the team, despite his/her skill level, has to be able understand the code by reading it. This helps young developers to be more confident in writing code.

Remove unnecessary code comments

Of course, some code can be very complex. I know that and I have seen that many times. Here I would add proper documentation and code comments.
Don't get me wrong. I'm not a fan of code comments or in Javascript JSdoc. Or at least not aslong as I don't need them. ;)
I don't need any comments to read that this function takes X amount of arrays and merges them together into a new array.

function mergeArrays(...arrays) {
  let mergedArray = []

  arrays.forEach(array => {
      mergedArray = [...mergedArray, ...array]
  })

  return mergedArray
}
Enter fullscreen mode Exit fullscreen mode

Adding JSdoc to this code does not improve the readability. I expect that my team members know what the spread operator is. And if they don't, they should ask about it during the code reviews.

And let's not forget the commented code blocks. Only one solution for that: DELETE THAT CODE. Git has the amazing feature to checkout old code, so why leave it in comments?

Please stop making a junkyard of your codebase.

Focus on naming

If you look at the name mergeArrays, it should be very clear that this function combines X amount of arrays into a new one.

I know that naming things is hard. And the more complex the function, the harder the naming part will be... I use a rule to make naming easier for myself. Here's how I do it.

Imagine a function that merges 2 arrays of numbers and generates a new unique list of numbers. How would you name it? Something like this?

function mergeNumberListIntoUniqueList(listOne, listTwo) {
  return [...new Set([...listOne, ...listTwo])]
}
Enter fullscreen mode Exit fullscreen mode

The name is not that bad, because it does what it says. The problem is that the function is doing 2 things. The more a function does, the more difficult it is to name it. Extracting it to 2 separate functions will make it much easier and more reusable at the same time.

function mergeLists(listOne, listTwo) {
  return [...listOne, ...listTwo]
}

function createUniqueList(list) {
  return [...new Set(list)]
}
Enter fullscreen mode Exit fullscreen mode

Of course it's easy to create a beautiful oneliner without calling a new function. But sometimes, oneliners are not that readable.

If statements

I could not find a name for this problem... See! Naming is hard...
But I see this a lot.

Problem

if(value === 'duck' || value === 'dog' || value === 'cat') {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Solution

const options = ['duck', 'dog', 'cat'];
if (options.includes(value)) {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

By doing this, you create a readable piece of code which looks like an English sentence.

If options includes value then ...

Early exit

There are a dozen ways of naming this principle, but I picked the name "Early exit".

So let me show you a piece of code. I'm sure you saw something like this before.

function handleEvent(event) {
  if (event) {
    const target = event.target;
    if (target) {
      // Your awesome piece of code that uses target
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Here we are trying to check if the object event is not falsy and the property target is available. Now the problem here is that we are already using 2 if statements.

Let's see how you could do an "early exit" here.

function handleEvent(event) {
  if (!event || !event.target) {
    return;
  }
  // Your awesome piece of code that uses target
}
Enter fullscreen mode Exit fullscreen mode

By applying the "early exit" here, you check if event and event.target is not falsy. It's immediately clear that we are sure that event.target is not falsy. It's also clear that no other code is executed if this statement is falsy.

Destructuring assignment

In javascript we can destructure objects and arrays.
According to the documentation, found on developer.mozilla.org, the descructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

Some code samples

// Destructuring an object
const numbers = {one: 1, two: 2};
const {one, two} = numbers;
console.log(one); // 1
console.log(two); // 2

// Destructuring an array
const numbers = [1, 2, 3, 4, 5];
const [one, two] = numbers;
console.log(one); // 1
console.log(two); // 2
Enter fullscreen mode Exit fullscreen mode

The problem with destructuring is that it sometimes creates a bad name for a property. The perfect example is fetching data from an API and receiving a response object which has a data property.

const url = "http://localhost:8080/api/v1/organizers/1"
const response = await axios.get(url)
const {name} = response.data
Enter fullscreen mode Exit fullscreen mode

This code sample indicates that you are fetching an organizer with id 1. The organizer object has a name, and you destructure it. Nothing wrong with that.
This code works and is fine. But why is the name still name? Will that be the only name property in the whole scope? And from which object is it the name again?

Avoid these questions by renaming the property.

const url = "http://localhost:8080/api/v1/organizers/1"
const response = await axios.get(url)
const {name: organizerName} = response.data
Enter fullscreen mode Exit fullscreen mode

This code becomes more readable. Everyone will know that the variable is the name of the organizer.

The boy scout rule

Ever heard of the phrase: "Leave it better than you found it"?
Well, this is exactly what the boy scout rule is. Leave the code better than you found it. Did you find a code smell? Refactor it! Did you find a unused variable? Remove it!

I like to compare it with a room cleaning situation. Let's imagine that everyone in your house leaves the dishes on the sink, puts all garbage in the hallway and leaves all the laundry in the bathroom. But every Sunday, you have to clean up the whole house and it takes well over 4 hours. Would you like that?

I'm sure that the answer is no. So if everyone immediately cleans up little parts of the house, the work will be smaller on Sunday.

This is the same with codebases. If every small code smell is left in the codebase, no one deletes unused variables, the linter is going crazy and has about 77 warnings. There will be a lot of clean-up to do, but if everyone takes his responsibility and applies the boy scout rule, a lot of the problems will be solved.

Code style

Last but not least. Determine a code style in your team.
I don't care if you like single quotes or double quotes, spaces or tabs, trailing comma or no trailing comma. Pick 1 style and stick to it. You can do this with a linter and/or a prettier.

There are so many tools to use to fix these kind of issues. My favourite is a pre-commit hook using Husky. Prettier also has a page in their documentation about pre-commit hooks.

This pre-commit hook always runs the configured command before every commit. If you configure it in the correct way, it runs the prettier and applies all the rules on all files. This makes sure that the team always has the same code style without any bad code.

Conclusion

I know that some rules are obvious and others are not. But as a full-time developer I get to work on different codebases. The importance of these rules only become clear in larger codebases. But that doesn't mean that you should not apply it in your smaller projects. Improving your code quality will help you to be more efficient in your smaller projects. It will also help your team with reading the code and approving your pull requests. As I said, readable code is more maintainable, but it also has many more advantages.

If you wish to learn more about clean code, you should read Clean Code by Robert Martin. If you like my content, make sure to follow me on Twitter where I post all the links of the blogs I release. I try to release 1 every week on various topics. Some of my content will be available on Medium.

Photo by Kevin Ku on Unsplash

Discussion

pic
Editor guide
Collapse
imjoshellis profile image
Josh Ellis

Great post!

Consider specifing the language in your markdown code blocks because Dev.to has syntax highlighting!

You can do this by adding the language after the first three backticks at the start of your code block:

// code block starts with '''js (but with backticks instead of ')
const fn = () => {
  const x = "hello"
  return 3 + x
}
Enter fullscreen mode Exit fullscreen mode

vs

// code block starts with just ''' (but with backticks instead of ')
const fn = () => {
  const x = "hello"
  return 3 + x
}
Enter fullscreen mode Exit fullscreen mode

Not sure that makes sense. The parser makes it difficult to explain. Here's a quick GitHub gist that will let you check out the raw text of this comment: Gist

Collapse
dvddpl profile image
Davide de Paolis

Wow. Cool suggestion. I do this all the time in Readme files, but never tried on DEV. To

Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

Oh okay, thanks! Did not know that! 👏

Collapse
babakks profile image
Babak K. Shandiz

"Guard clause" is the commonly used title for early exit.

Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

Oh thanks! Learned something new today!

Collapse
baenencalin profile image
Calin Baenen

Honestly, I get stuck with how to clean my code, but this is my rule of thumb. What do you think?:


# Imports
import modulestobeimported;
import modulestobeimported2;


# Do <thing>.
x = thing1(); # Make "x" a thing.
completething(x);

# Related things.
y.dothingwith(x, null); # Make Y do a thing to X.


# Semi-related.
a = str(y.getdata()); # Get graphing data.



# Unrelated things.
z = extrathings(); # Comment to clarify, if it seems confusing.



# Main method.
def Main():
    pass;

Enter fullscreen mode Exit fullscreen mode

The main (class and/or) method is considered unrelated to anything else, while, unrelated sections are 3 lines down, semi-related, 2, and related 1.

They don't always have to be labeled with comments, but, I think it looks neater.

One example is the CPane class from my most recent post (here).

Another is:


// Get graphing data for the money made from the server.
Tuple[] d = server.getGraphPoints("money-made");

// Graph some data.
Graph g = new Graph(
    new Tuple<int>(0, 0),
    new Tuple<int>(1000, 1000),
    d
); // Make a 1000 by 1000 graph to show the sales.


// Make a display to show the graph.
JFrame window = new JFrame("Data Graph");
window.add( g.getJPanelRepresentation() ); // Get the repr of the graph.

Enter fullscreen mode Exit fullscreen mode

Again, tell me what you think of my writing style, I'd love to hear feedback.

Collapse
emilesteen profile image
Emile Steenkamp

You don't need comments to explain what your code is doing. Better practice is to use code to explain what the code is doing.

for your last example you could rather do this:

Graph graph = getGraph("money-made");
displayGraph(graph);

function getGraph(String source) {
    Tuple[] graphPoints = server.getGraphPoints(source);
    Graph graph = new Graph(
        new Tuple<int>(0, 0),
        new Tuple<int>(1000, 1000),
        graphPoints
    );
    return graph
}

function displayGraph(Graph graph) {
    JFrame window = new JFrame("Data Graph");
    window.add( graph.getJPanelRepresentation() );
}
Enter fullscreen mode Exit fullscreen mode

In this example out functions are telling the developer exactly what is happening and splitting the code up into sections instead of comments. A common issue is that comments can lie. If you update the code and forget to update your comments your comments will be lying and can confuse you. If your code is readable you shouldn't need comments to explain what is happening.

Uncle Bob explains the use of comments much better in this talk:
youtu.be/2a_ytyt9sf8
and I would recommend watching the entire clean code series if you have time.

Collapse
baenencalin profile image
Calin Baenen

Is it bad, or to a disadvantage to use comments, then?

Thread Thread
darlantc profile image
Darlan Tódero ten Caten

Yes, experience teaches us that comments must be the last resource to be used only when the logic is very hard to explain. Even so in most times is better to break that complicated logic into multiple small functions to be easy to read that code later.

Always try to name all variables, functions, and classes with meaningful names that self explain itself, avoiding the usage of comments.

Also, another problem with comments is that when the code changes very often the developers don't update the comments (the linter don't tell us that they are wrong now) and they don't reflect anymore the current logic of the code.

Collapse
evanyoung1996 profile image
EvanYoung

Great post!

I'm from HelloGitHub, a nonprofit organization in China. I am reaching out to you to ask if it's OK for us to translate your posts, "Clean up your code by applying these 7 rules", into Chinese and publish it on our WeChat official account. You own the copyright of course.

How does that sound to you?

Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

You can translate it and publish it, thanks for asking! I appreciate the interests!

Collapse
bebetos92 profile image
Alberto Talone

Nice article!
I really love to boyscout rule but I'm always afraid to destroy something 😂
About the team code style, every team should think about that, and a lot of them don't know or don't want to "waste" time about that..what a pity!

Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

For the boy scout rule, the tests should help you to not break something. And most of the time people forget about very important parts before they start a project. Like the code style.

Collapse
felipemartins81 profile image
Felipe Martins

Good solution for 'If statements' issue!
What about this way?..

switch (value) {
    case 'duck':
    case 'dog':
    case 'cat':
        // ...
        break;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

In this case this would be a good solution, but it gets really big when you have to check 10 options for example! The switch statement is also not available in Python for example.

Collapse
kretaceous profile image
Abhijit Hota

The reason I use JSDoc in VS Code is for its autocomplete feature! But I do agree a function should be as self explanatory as possible.

Great write-up! 😄

Collapse
redheadcoder profile image
Esther

you should probably point out that destructuring is ES6 syntax, which may not be compatible with every codebase

Collapse
jonrandy profile image
Jon Randy

Why so verbose? Why not just:

const mergeArrays = (...arrays) => arrays.reduce((merged, arr) => [...merged, ...arr])
Enter fullscreen mode Exit fullscreen mode

It's equally readable

Collapse
joachimzeelmaekers profile image
Joachim Zeelmaekers Author

Well it’s just to make the code snippet clear. As I said in the article, it could be replaced by a nice oneliner, but that’s not really the point of this article.

Collapse
yuvrajkhavad profile image
Yuvraj Khavad

Hey, Thanks for good solutions, thank you for sharing with us.

Collapse
phongduong profile image
Phong Duong

Thank you for sharing. I don't use the comment for my code. If I read my code after 1 month, I sometimes don't understand what it does and have to spend times rereading the whole function or file

Collapse
amitavmishra99 profile image
Amitav Mishra

great piece ! covered some cool tips. Thanks