Easy little steps towards better Code Quality
Computers are smart enough to understand your code but it’s the humans who require more clarity
As a developer, the code we write is most likely to be re-visited by other developers (including us) from time to time. This makes us responsible for writing a good-quality code that not only does the job efficiently but actually is easy to follow and understand.
The code should be self-explanatory and flexible for changes. Other developers should be able to understand the intent and logic behind the code without burning a lot of time. A poorly written code can make other developers go back and forth without being able to get the gist of it. This quickly becomes a challenge when you are working in a fast-paced environment and begins deterioration of code quality.
Whenever I write code, I always put in extra efforts to make it more easy to read and understand. It is the intent that matters followed by your knowledge. After having reviewed multiple pull requests, I realised that there are a few steps which are tiny but can be good initial steps towards a better code quality.
The tips below might be more specific to JavaScript but it should not stop you from understanding the intent behind using them
Order of if-else statements
Needless to say, if-else
is one of the basic building blocks of our applications. Almost every module we write uses the if-else
logic.
Usually, the length of code in the if
and else
blocks differs. In the extreme cases, one of them might end up having 2x or more lines of code than the other block.
In such scenarios, writing the smaller conditional block in the beginning saves time of the reader.
In the code snippets above, the one on the left has the larger piece of code in the first conditional block. This makes the reader go through all the code even if he’s interested in the else
part. This gets worse when you have a larger piece of code.
Where as, in the right snippet, with the shorter piece of code written first, the reader can skip the rest of the code below it if that’s what he was looking for without having to scroll all the way down to find the inverse condition.
In some cases you may also skip the else part if you’re throwing/returning from the first block. The snippet on the right is a good example where we can skip the else
part as we’re throwing an error in the if
block.
Accessing a property for loop’s condition in for loop
Let’s suppose you have an array of users
with length ≥ 1000 and you want to traverse through all the users to do some processing. Using the users.length
as the conditional check for for
loop makes the processor take an extra step of accessing the value of the length
property after each iteration.
We can simply pull out this value in a variable and use it as the conditional. This is just a direction to think about when looping over larger data sets.
Over engineering is not a very desirable output but it should not keep you from writing better code either. You must maintain a good balance and should not leave such opportunities unattended if you know there’s a better way of doing it.
Using Math.min() and Math.max() for comparisons
There are times when we need to compare some values and return the one that matches our desired condition. Many such cases are suitable for using Math.min()
and Math.max()
Notice the calculation forlargerWidth
and largerHeight
using ternary operator below
Using Math.max()
instead of ternary operator makes the code more readable and short. Not only it improves the readability but also declares the intent of the logic.
Using setTimeout()
instead of setInterval()
The setTimeout
and setInterval
APIs provided to us are very useful. setTimeout
executes the given callback once after the given time and setInterval
keeps on executing the given callback at the given interval.
Depending on the use case, we may want to run a callback function repeatedly once the previous function call is done. This is not guaranteed by the setInterval
API. It will blindly run the given callback function after every x
ms given to it (with some expected delay).
To solve this problem, we can use the setTimeout
API and call the function repeatedly with setTimeout()
.
In the above example, we schedule the first call to callApiRepeatedly()
with the setTimeout
function and then schedule the subsequent calls from inside the callApiRepeatedly()
function. This ensures that no two executions of callApiRepeatedly
will coexist. This is not guaranteed by the setInterval
function as it will keep executing the callApiRepeatedly()
function at the given interval irrespective of the previous call’s completion status.
Default Parameters
Default parameters were introduced in ES6 and have become friends with our code very quickly. They give us the flexibility to set a default value if no value is passed for a parameter. This, however, sometimes creates confusion. The default parameters are only used if there is no argument passed, basically the argument is undefined
. Expecting them to work with falsy values should be avoided.
Another great feature of default params is that we can access the params that are defined in the order before. The example below demonstrates this.
Checking existence of a key in object
Many times we want to check if a key exists in the object or not. While there are multiple ways of achieving this, sometimes developers tend to fall into the trap of checking the existence like myObject[key]
which is not the correct way of checking.
Let’s see how we can perform this operation using the in
operator and Object.prototype.hasOwnProperty
function, basis our requirements.
One Bonus point to note here! We could also do foo.hasOwnProperty('qux')
which would have returned true
but this is not considered safe. Calling foo.hasOwnProperty('qux')
triggers the JS engine to find the hasOwnProperty
key in the foo
object first. If the key is not found, it travels down to the prototype object and finally reaches Object.prototype.hasOwnProperty
function.
If we modify the foo
object and add a bogus function that always returns true
, we can break the code or misuse it. This is true for almost all the prototype functions.
So, it is considered as a better practice to use the Object.prototype.hasOwnProperty
. See the example below.
Although, another function has been added to the Object.prototype that eliminates all the hassle and makes it easy to achieve this, Object.hasOwn()
These were some of the suggestions that I think are too simple to use but would add to your code quality and readability. Always, try to write such a code that no matter who reads it, irrespective of his experience, should be able to understand the intention behind it.
Feel free to share your thoughts in the comments. I’d love to read them.
Connect with me on LinkedIn, Divyanshu Bhatnagar
#KeepCodingAndGrowing!