The priority of having clean code is often unknowingly pushed to the background. We are all aware of its importance, but when time is precious we tend to get fixated on making a functionality work. The concern of readable and consistent code is saved for later. Once bad code makes it to production, people often accept it. Rewriting perfectly fine working code usually does not get a high priority and maybe more interesting, how can you convince the customer to pay for it? The code keeps existing, consuming more and more of that precious time…
This is why it is important to invest time in writing clean code, always. Not ‘when there is some spare time’, ‘when this part will be improved’ or ‘when this prototype is approved and we rewrite the whole thing’. Just always.
Clean code is different for everyone and that makes it rather messy. Thankfully programmers are trying to reach some sort of consistency in code standards. For example, by reading the book Clean Code. This book is full of guidelines for consistent, readable and quick to understand code for every programmer, not just the ones who read the book. For this blog I figured it would be nice to share some highlights that can be easily adapted into your daily programming work.
Meaningful naming is a big step in the direction of clean code. Thinking about the right name can take a while. When done right this is completely worth it. A name has to be informative for anyone who reads it. Not something that is only known by members of the team or an unknown abbreviation. No overcomplicated technical combinations and, how hilarious it may be, not an inside joke. A meaningful name is serious and consistent. When naming something in your code, ask yourself, is the information in this name meaningful for the reader? Aren’t some of the things obvious? For example, declaring a variable
progressbarAnimation in the class
Progressbar may seem clean. But declaring a variable
animation in that
Progressbar class is just as clean. Or maybe things are not obvious at all. Like using hardcoded numbers in functions. It is hard for a reader to understand why a variable has to match a hardcoded 5, while he probably can quickly understand why a variable has to match the constant
Keep it simple
Avoid using variable types in a name like
nameString, simply because most of the time it is not necessary.
EnemyList can easily be named to
enemies and it is still obvious they are multiple enemies. Besides there is no naming refactor needed when the data structure is changed to something other than a list. A variable regarding a name obviously won’t be of type
int so what is wrong with
name instead of
Functions are small, do one thing and tell a fluent story. That is what we should aim for when writing functions. A proper function does exactly what you, from the name, expect it to do. If the function is complicated, accept that the name can be a bit long. However, if the name becomes too long, it may be wise to reconsider the cleanliness of the function. Is it really doing one thing? An easy guideline to keep in mind when naming a function is to create a verb-noun pair. Name the function after the verb of the task it is performing, while naming the parameter after the noun describing the object that is necessary for the task to be fulfilled.
select(subject) and so on.
Spare some arguments
Having a function requiring arguments influences the readability. Easiest is a function with no arguments, or just one argument as described above. Two or more arguments causes confusion. How does the reader know the difference in behaviour depending on the different arguments? Which parameter is used for what? It is inevitable to read the whole function to know for sure this is the function you want to use.
Avoid two or more arguments by grouping arguments into classes:
spawn(int x, int y, int z, int typeId);
spawn(Vector position, int typeId);
or even better:
Avoid booleans as an argument. Reading the first line of this function
newCustomer (customer, isPremium) leaves the question of what the function does different depending on the boolean value. Separating the functions into
newPremiumCustomer() makes it clear by only reading the function names. Besides, this creates two functions that perform one clear task while the first function performed a different task depending on the boolean.
If reading these simple guidelines made you wonder what else improves your clean code writing ability, check out the rest of the book. Or check out uncle Bob’s live talks.