General Coding Guidelines: Clean Code From Day 1
Help your teammates understand, reuse and extend your code easily, and help them not to introduce bugs while they are at it.
Good coding habits make working with your team a piece of cake
The life of a programmer is beautiful when the code they work with is beautiful. Through your code, you have the power to affect the life of your fellow programmers:
- They will rejoice/panic when they know they have to work with the code you wrote.
- They will spend 10 minutes/1 hour understanding the code you wrote.
- They will introduce 0 bugs/2 bugs when they edit the code you wrote.
I have been there, in all of those scenarios. I know that every programmer focuses on building the functionality they want, but not all of them pay attention to how they build it. They tend to forget that, eventually, someone else will have to read that code.
It seems silly that I took the time to write this article when there are tons of articles and books on the subject, but the sad reality is that I have seen bad coding habits in all kinds of environments: as a student in a master’s degree, as a programmer in a big company, as a programmer in a startup and as a freelancer working with other freelancers.
If you want people to rejoice with the idea of working with your code, just focus on two things: make your code readable and make your code robust.
Make Your Code Readable
Your teammates and your future self should be able to understand, reuse and extend your code seamlessly whenever they need to.
1. Use Meaningful Names and Avoid Made-Up Acronyms
// Avoid this
label1.text = dog.name
label2.text = dog.breed
label3.text = dog.int_temp
label4.text = dog.breed.int_fact
How will your teammates know if the values are being assigned correctly if the labels don’t give any hint about the information they are supposed to show? and how will your teammates know what do
int_fact mean exactly?
// Do this
name_label.text = dog.name
breed_label.text = dog.breed
internal_temperature_label.text = dog.internal_temperature
interesting_fact_label.text = dog.breed.interesting_fact
Your teammates will appreciate it if you save them the time of looking through the code to know what something means or what something is used for. To make sure that the name of a variable, class or function is meaningful enough, you can ask yourself:
If I see this name alone in the source code, will I know what it is for without looking further into the code?
2. Follow the Conventions
I cannot tell you exactly how to name your variables, functions and other stuff because I don’t know what programming language you are using. Each language, and sometimes each project, has a specific coding convention.
Every time you learn a new language, one of the first things you should do is read its corresponding coding or style guidelines, so that you can do things the right way from day 1. If you wait too long to learn the right way to code in your specific language, you’ll start developing some bad habits.
Note that if you are working on a project and the project’s team has defined a coding convention that is different from what you expect, you should follow that convention. The important thing here is follow the convention of the project or platform you are working on and make your fellow programmers happy.
3. Keep Functions Short and to the Point
How short? around 20 lines of code or less. And yes, nobody likes to count lines of code while coding. Thankfully, you don’t have to do that, you can use the old recommendation: the function should fit entirely on your screen so that you don’t have to scroll to read it completely.
Both of us know that nowadays some screens are HUGE. So you can adjust that recommendation and make the functions fit half of your screen, 1/3 of your screen, or whatever portion of your screen works for you.
Keeping the function short isn’t enough. You have to keep it doing what the name PROMISED it would do. If the function says Annie will eat an apple, then when the function is executed, Annie should be eating an apple and not oranges, grapes or strawberries. Keep your functions short and to the point, so that your teammates don’t have to keep a mental map of everything the function does because its name doesn’t match its body.
Update: As the reddit user lykwydchykyn pointed out in this comment, it's dangerous to blindly stick to a given amount of lines when writing a function. Beginners might be tempted to write "hideously dense, long lines of code to keep functions under a line count limit", or "bucket brigade functions, where a single procedure is just broken up arbitrarily into functions that call one another (i.e.
step1() gets to line 19 and then calls
step2(), which gets to line 19 and calls
step3(). No individual step makes any sense in isolation.)". So, beginners should keep in mind that it is more important to keep your functions meaningful than sticking to a given line count. Also, even when programming languages allow you to place two or more statements in the same line, it is better to write each statement in its own line. And finally, IDEs display a right margin that indicates the recommended line length. You can use that right margin to know if your line is growing too much.
4. Update Member Variables Explicitly
Other guides explain this more broadly by saying:
Functions should not have side effects.
Updating a member variable of a class IS a side effect of a function if the function doesn’t indicate that it will be updating that variable.
This part is tricky because we usually update the private members of a class inside its methods when the class represents a business domain entity. For example,
car.move will update the car’s position variable and that’s OK because
Car represents a business domain entity. That’s not the kind of classes I’m talking about here.
Think about the classes used for an Android
Activity or an iOS
UIViewController. In those classes we have lots of members variables that hold all kinds of information. We may initialize some of those variables inside functions that do some other stuff. That is BAD.
What I prefer to do in this situations, is make a function that returns a value and assign that value explicitly to the member variable. When my teammates see the function call being assigned to the variable, they automatically know that the function is being used to set that variable, and they don’t have to look into the function to know if it is changing the value of the variable or not.
5. Use Comments Wisely
Your comments should not explain step by step what the code is doing. Your excellent variable/method/class naming skills will take care of that.
Your comments should be cleverly placed to say WHY something has been coded in a certain way. Jeff Atwood explains this wonderfully in his article Code Tells You How, Comments Tell You Why.
If you find yourself thinking:
I implemented this in this way because of that important technical decision.
Then that’s some code that needs to be commented. If you don’t add the comment, your teammates might introduce a bug when they edit the code because they are not aware of the important technical decision.
Finally, this is what your teammates actually think when they see commented code:
Oh, some comments, but I understand what the code does, I don’t need to read them. I’ll just change this little piece of code.
And BOOM, the comments are outdated. So this is another reason to avoid not needed comments and only adding comments that you actually want people to read.
True story: I have seen a comment next to a magic number indicating what the number means. A comment next to a magic number doesn’t make the comment a good comment.
Make Your Code Robust
Your teammates and your future self should be able to edit your code without introducing bugs in the process.
1. Avoid Duplication
The famous DRY (Don’t Repeat Yourself).
This is harder to achieve than you might think. When you are under pressure, you start working on your feature right away without checking the existing code to see what functions already exists. By the time you finish writing your code, you realize that you inadvertently wrote a function very similar to one that already existed. But now you are finished, you are tired and want to go to sleep. It seems like a waste to invest your time in extracting the common behavior into a separate function. After all, the similarity is so small… Why bother?
// Written by Tommy two weeks ago
* Very cool code for setting an alarm <- DUPLICATED
* Very cool code to do it hourly
}// Written by you just now because you didn't see Tommy's code
* Very cool code for setting an alarm <- DUPLICATED
* Very cool code to do it daily
If you leave that seemingly innocuous piece of code duplicated, doom will reach you. Because, one day, the code for setting an alarm will change and someone will change it in just one of the functions if the other function is too far away from the first one to see it. And no one will notice that there is one function still using that old, deprecated, and maybe buggy piece of code.
Do yourself a favor and give a quick view to the existing code BEFORE you start working. You can see if there is something you can reuse to make your work more efficient.
True story: I have seen two functions that do similar things one below the other, with some common behavior that could have been refactored into a third function.
2. Avoid Hard-Coded Strings and Magic Numbers
Every string should be a reference to a string resource, an enum or a constant. Why? because you think that you’ll only use that string this one time. What you don’t know is that there will come a fateful day when that string is used in another place too. And after that, will come an even worse day when someone edits that string, and they only edit it in one place because they have no idea it exists somewhere else. Only very careful people do a “Find in project” for every hard-coded string they update.
Avoid your teammates a headache and give them a single place to update a string that is used throughout the code: a good old constant (or enum, or string resource).
The same thing goes with magic numbers. They may be even worse than hard-coded strings, because you have no idea of what that number represents. Take a look at the following example.
// Avoid this
How do you know what the system is supposed to do in status 1 or status 2 if you have no idea of what those numbers represent? Keep your code auto-documented by placing numbers in a constant or an enum.
// Do this
True story: I have seen Android preferences keys hard-coded to read and write values to the shared preferences.
True story: I have seen code where a plain number is assigned to a variable called ‘status’ and next to the number, a comment indicating what the number means.
3. Check Values From Unreliable Sources
Or, in the words of my friend Gabriel Aguirre:
Don’t trust the server.
You have a server, and it has promised you to return a JSON objects with all the values you want: the name and breed of the dog. You trust the server and you use those values directly in your code:
// Avoid this
// This code throws a null exception
// if the JSON doesn't have the 'name' or 'breed' properties
dogName = dogDataJSON.get("name").getAsString();
dogBreed = dogDataJSON.get("breed").getAsString();
If the server doesn’t keep its promise, your app irreparably crashes. But it doesn’t end there, it’s not just the server whom you can’t trust. You can’t trust data coming from ANY unreliable resource. Something could have gone wrong with the generation of the information you expect and you might find an unwanted null value.
// Do this
// Do a null check before working with data obtained from the server
dogName = dogDataJSON.get("name") != null?
dogDataJSON.get("name").getAsString() : "";
dogBreed = dogDataJSON.get("breed") != null?
dogDataJSON.get("breed").getAsString() : "";
True story: I’ve had this error twice with SOAP objects and with JSON objects. I’ve learned my lesson.
4. Always Write the Braces Around Single Line Blocks
We all know that when you have an if statement with just one line, you can omit the braces. Please don’t do this. This is extremely error prone, and I’ll tell you why:
Your code will work perfectly fine until a teammate is working on a feature that needs to add just one more statement to that
if block you wrote. Your teammate comes to your
if, adds the statement and then keeps working on the feature. Guess what, your teammate forgot to add the braces because no one pays attention to the braces when they have other things in their minds. The
if statement still has one statement and now there is a random orphan statement executing without anyone noticing. When the software breaks, your teammate will spend precious time trying to find a bug that apparently came out from nowhere.
Make life easier for those who will come after you and add the braces in your single-line
for and any other block that allows optional braces.
True story: I have seen this kind of bugs happen in the technology departments of big companies. Even experienced programmers forget to add the braces.
Write Everything Code-Related in English
This may seem obvious for native English speakers, but I have seen code from Spanish speaking programmers with comments, variable names and function names written in Spanish. This is not a good practice.
Why is it better to write code-related stuff in English?
- Names in English are shorter, therefore your variable names and function names are shorter and easier to read if you name them in English.
- It’s easier to ask a question in Stack Overflow and copy/paste your code without translating the comments or variable/function names for people around the world to answer your question.
- It allows you to seamlessly add a new team member from another country to your project, because every programmer knows English.
- Getters and setters: it’s weird to have getters and setters that don’t start with get and set. So some people mix the get/set word with the Spanish word for the object they are getting/setting. That’s kind of weird.
So what you should write in English? Everything: classes, variables, functions, comments, log messages and even commit messages so that team members from other countries can review the repository without problems.
One problem I have faced with this practice is:
I only know the business domain language in my native language because that’s how my customer explained things to me. Naming things in my native language is so much easier. What should I do?
FEAR NOT! Google Translate is your best friend. Just translate the terms and use the English equivalent in your app. I have done this several times and I have never regretted it, but I have regretted not using English as the single language in my code base.
I know it’s difficult to apply all these guidelines while you are coding because you are focused on the functionality you are writing and you probably are short on time and that’s OK. But once you finish writing a piece of functionality or you are ready to push some code… STOP! and read the code. Read it and and you’ll realize if your teammates will be able to understand your code easily or if they’ll have a hard time modifying it.
Every IDE nowadays allows you to refactor easily, so it will only take a couple of minutes to extract that piece of functionality into another function, rename some variables and add some comments. Your teammates and your future self will appreciate it.
Many books and articles have been written about this subject. One I particularly like is Clean Code: A Handbook of Agile Software Craftsmanship.
Thank you for reading and enjoy your programmer life.