5 Tips for Cleaner Code

Radoslav Radenkov
paysafe-bulgaria
Published in
7 min readFeb 17, 2022
eyeglasses in front of monitor where different tabs with codes are opened

“It is not enough for code to work.”
Robert C. Martin

The code should be clean, readable, and optimized. Had you ever experienced the feeling of trying to read a code with messy syntaxes, smashed-together huge blocks of codes or just some randomly dropped functions? Yep, we had all been there. When a team is working simultaneously on a code, this is probably an everyday problem. There are some hacks that will literally ease your life by learning how to write a clean code.

In this post I will share some good practices that I’ve learned in my software engineering career that can make you code “cleaner”.

What is clean code?

First let’s start with what is clean code. When you hear clean code what is the first thing that comes to your mind? There certainly isn’t one definition what makes code cleaner. Everyone has something in their head, so I’ve asked several people what their definition is. Here is the gist of what I got:

Easy to understand and change — code is written in such manner that tries not to confuse the reader and there are no hidden gotchas;
Simple and direct — like previous one said in different words;
Written with care — some say that writing code is a craft. And as any other craft putting care into it gives better results;
Efficient — uses proper algorithms in an optimal way;
Tested — has sufficient test coverage. Making it safer to change and easier to reason about its intent;
Avoids duplication — There isn’t much more to say that duplicated code is bad code and can lead to lots of problems.

In this post I will focus on the first two, writing code that is easy to understand and change. Even though we write our code to run on computers, it will also be read by humans. Computers understand all code if it compiles. But for humans we need to put a bit more effort. Writing simple and direct code will help others that read it and will help you when have to change something one year from now. And as a bonus you will very likely start to receive more favorable code reviews 😉

Naming things

Naming is major part of writing code. You need to come up with lots of names. Names for variables, functions, function arguments, classes, directories and on and on. Sometimes there are defined rules which help, for example when naming a micro-service or repository for your company, but often there aren’t, and we are left to our own imagination. Which sometimes fails us. There are only two hard things in Computer Science: cache invalidation and naming things.

Phil Karlton
https://www.karlton.org/2017/12/naming-things-hard/

So, can we make things easier? Following certain rules is a good start. Each programming language has its own conventions, what should be capitalized, what shouldn’t. Whether to use camelCase, snake_case, kebab-case, or something else.
Then there are the rules that come from Object Oriented Programming. Classes are nouns because they represent objects, methods are verbs since they do things. But with interfaces thing get tricky. There are different conventions for interfaces. Some prefix them with I IList, other suggest suffixing them with -able or -ing — Equatable, ProgresReporting. My first suggestion about this is to follow the conventions in the code base you are working on. If you have an option to choose then I will suggest dropping any “I” prefixes or any “Protocol” or “Interface” suffixes and name them as you would name any type. The idea of interfaces is to hide the implementation, so implementing type should come up with a good name.
Apart from conventions something that will help a lot is to use names in English with correct spelling. Most programming languages support Unicode characters, with some even allowing you to use emojis for variables and functions. So might look cool and tempting to define log function like this:

Log.⚠️("Warning")
// instead of
Log.warning("Warning")

But in the long run you will see that is not very practical. IDEs auto complete will be harder to use. Searching through you code will also get harder. Modern IDEs have spell checking so just enable it, everyone will be grateful next time when trying to find something code about accounts (and not accounts 😁)

Tip 1: Get familiar with naming conventions and follow them

In addition to conventions there are a few other advice I can offer.
Don’t encode type information into the name. There were times, names were length constrained and IDEs weren’t providing so much context and things like Hungarian notation were good practices. But now they are not needed. Name like accountList doesn’t give any additional information that you can’t see on first glance. Simply accounts is shorter and gives enough context — a collection of Account. When you need to use it, IDE will show what is its actual type and offer appropriate methods.
Don’t rely on comments to explain a name. Try to come up with a better name instead. We will go into that topic in the next section.
Take context into consideration. “State” can mean one thing in context of address, state in a country like USA or India, or completely different thing is the context of object state.

And the most important advice I can give about names is that they should reveal intention. What is this thing intended to be used for or do? Which I know sounds easier that actually is. It takes more time to come up with such names or may require several iterations of renaming something. But start following it and you will see that the result is worth is. Reading the code will start to make more sense.

Tip 2: Names should reveal intention

Comments

We have all seen comments like this:

// Get primary accounts with non zero balanceaccounts.stream()
.filter(account -> account.isPrimary() && !BigDecimal.ZERO.equals(account.getBalance()))
.collect(Collectors.toList());

What information do they give us? Nothing more from what you can learn from reading the code. Some of you might say — when I see such comment, I won’t read the code because it says what it does. But will you trust the comment. For sure I won’t. I’ve seen more than enough examples where code was changed, and comment wasn’t. All it does is to bring more noise and in the worst case can even propagate misinformation and confusion. So, comments can actually make code worse.

We shouldn’t use comments to explain bad code. If you feel you need a comment, then consider rewriting your code with better names and shorter functions.

Don’t comment out sections of your code and live them like that. Just delete them. We have version control systems like GIT and SVN if you need to see previous versions. Also be mindful of TODO comments. Not everything can be implemented at once, but also leaving a TODO doesn’t mean you’ve done your job and is some else responsibility to finish it.

What you should use comments for, is to explain your intent. Why something is written, not what is written. The former is clear from the code.

Tip 3: Comments shouldn’t explain what the code does, but why it does it

Functions

We all have been lost in reading 100 lines long function. In the middle you forget what was going on 20 lines above. Or there were so many nested if-else statements, you no longer know which one ends in particular closing brace. Modern IDEs help a lot, they highlight brace pairs and allow collapsing whole statements. But this is not an excuse to write such code.

The one most important advice you can follow about functions is to keep them small. If you look around the internet, most people will stay that it shouldn’t take you longer than a minute or two to understand what function does. Splitting long functions into shorter ones helps a lot with readability and understandability of your code. And if you’ve heard about deep call stacks and worry about performance penalty, you shouldn’t. If you have such constraints, you will know it :) For the rest of you, just try to keep functions short and in best case do one thing. Or said in SOLID terms, have single responsibility. Following this advice will also make naming easier. Because if you function does one thing, coming up with a good name won’t be that hard.

The second advice I can give about functions is to avoid side effects.

Side effects are like broken promises. Your function tells that will do one thing, but also does something else. It has a hidden secret. And if you are not careful when reading it, you might not notice it. Or maybe you can add a comment explaining that secret? No, you shouldn’t do that. Comments don’t make up for bad code. Rewrite your functions so they don’t have side effects and do what they promise.

Tip 4: Keep functions short and without side effects

My last advice will be a bit more general. It is about helping you code base stay in good shape. You can do this by following not only naming conventions, but also good coding practices and design patterns. I really hope there are such already in your code and if not, you can discuss it with your peers and introduce them. Try to keep things simple and reduce complexity. And lastly, you have probably heard about the boy scout rule. Always leave the code you change in better shape than it was before that.

Tip 5: Be a good citizen or boy scout ;)

These were my top 5 tips on how to write clean code that is easy to understand by others and your future you. I hope you agree with some or all of them. Or maybe you already follow them. I will be happy to hear your thoughts in the comments.

References:
Robert C. Martin — Clean Code: A handbook of agile software craftsmanship
Swift API design guidelines — https://www.swift.org/documentation/api-design-guidelines/
Quote: https://www.goodreads.com/work/quotes/3779106-clean-code-a-handbook-of-agile-software-craftsmanship-robert-c-martin
Featured Image Credentials: https://www.pexels.com/@kevin-ku-92347

--

--