Hi there! π
Recently, I was working as a software engineering intern at a startup as a back end developer. My task was to build the architecture & infrastructure from scratch using a modern server side framework Node.js. The co-founder who was also a developer in the team, introduced me to this word Cyclomatic Complexity
which sounds too geeky, and imposter syndrome just waved me from a distance π€£.
Hence, I looked up the term online and found it interesting to keep in mind while coding in not just JavaScript but any programming language.
Let's just address the elephant in the room:
Cyclomatic Complexity is a metric or a number which indicates how many execution scenarios there might be inside a file containing code.
(I doubt if that made sense, because for me it did not when i heard this definition for the first time.) π
πNote: An execution scenario is a block of code which needs to be tested on several required use cases.
The definition above simply means how difficult it is for a developer to read and understand when working on a new code base. Everyday software engineers read lots of code & during this process, they try to imagine and visualize how the code functions. The more execution scenarios they see, the harder it becomes for them to keep track of what is actually going on. This but obvious leads to buggy implementations and workarounds which may affect the performance of the code base when seen from a broader perspective.
There are some operators in JavaScript which increase complexity:
while | if | for | case | logical OR | catch | ternary operator | return
Let us take an example which shows a block of code which is complex:
if(condition) {
if(someAnotherCondition || oneMoreCondtion) {
for(let x in someObj) {
.... statements with more logical AND, OR conditions
}
}
}
Now, you could imagine how tough it will be for a developer to check what these conditions evaluate to.
Solution πββοΈ
So, what would be the solution to reduce complexity ?
Split your code into seperate functions! π²
A function will not only make sure that we don't repeat ourselves [ DRY ], but it allows us to define a scoped scenario which could be understood easily. The function name itself tells you what task does it perform which adds points to the readability score.
function authorize(user) {
const isOldUser = findUser(user);
if(isOldUser) {
// You are logged in!
} else {
createNewUser(user)
}
}
The above block of code shows a mock implementation of users being authorized. You can see, that functions are named appropriately which gives an idea to the reader what that function does without having the knowledge of the definition.
Tools π
To analyze the code, there are tools like eslint & jshint which help you to find the value of cyclomatic complexity per function. You have to define a maximum value after which the tool will start logging the warnings or errors. A value of 3 is set if you want to have your functions small & precise.
For functional programming, RamdaJS is a library which is designed specifically for FP and it makes straightforward to handle conditions and does not mutate user data.
const R = requires('ramda');
if(R.equals(page, 1)) {
// get posts for page 1
}
Here instead of using the ===
operator, we use Ramda's .equals()
method to handle the equality condition.
My Thoughts π¬
It is important to keep cyclomatic complexity under control and to keep it quite low, it requires practice.
I hope you liked my first blog post. Please share your thoughts in the comments. π
Signing off... βοΈ