Easing into Cyclomatic Complexity 
Tags: tutorial, javascript, computerscience
Published: 2020-04-05 19:23:29

---
title: Easing into Cyclomatic Complexity 
published: true
description: A brief introduction to Cyclomatic Complexity and why it is important
tags: #tutorial, #javascript, #computerscience
---

Most people reading this article might have or _will be_ in the situation of looking at a project's code and scratching their heads why they might not be able to reason about its outputs. This article is probably gonna help you at least understand why you might have this difficulty for certain modules. You are not alone in this.

## The reality

```javascript
function makeInitialState(x, y){
  const state = [];
  if(x.a || y.b){
    state.push(x.b && y);
  }
  return state;
}
```
The above is a generalized view of some code that you will encounter in the wild OSS community or on the project you are maintaining day to day.

Stand back for a second and imagine _x_ and _y_ being two known entities passed around your program. They are familiar, like _bookings_, _hotels_, _shirts_, _todos_  or anything you are familiar with.
Even in that scenario you will not be able to so easily reason about __when__ the output or side effect will be different.

__Maybe because its cyclomatic complexity is 4__...

## Intro to our program flow
_You can skip it if you feel like it_

One of the most important things that changed my view on reading but also on writing programs is coming to terms with _Cyclomatic Complexity_. The first thing not to do is being __daunted by the term__.
It is a software metric that was defined back in the old days of 1976 by  Thomas J. McCabe, Sr. and has been studied across the years, at some points also applied to official security standards like ISO and IEC.

When writing a program, we start with an empty abstraction, either that be a module, a class or a function. Going into this new abstraction, we define the things we wish to happen at the point this code is executed. You can think of these statements as points in the path your machine will run when you code executes.
```
   ○       // Entry
   ↓
   ⬢       // Statement
   ↓
   ●       // Exit
```
_There is only one path our code can take..._

This can be considered __the flow__ of our statements.

At some point, due to requirements or initial definition of our program, we have to add some logic that will:
- Loop through some statements (_while_, _for_)
- Decide if statements should be run or not (_if_, _else_, _switch_)
- Evaluate if the program should throw an exception and stop in its tracks (_try_-_catch_-_finally_)
- Branch out of the current execution (_break_, _continue_)

The simple conditional statement will change our path to something like

```javascript
function makeConditionalState(x){
  const state = createEmptyState();
  if(x){
    state.push(x);
  }
  return state;
}
```

_And with weird symbols:_
```
   ○       // Entry
   ↓
   ⬢       // StatementA -> Always executes
   ↓
   ⬢       // Conditional
   |  ↘    
   |    ⬢  // If conditional is true execute StatementB
   ↓  ↙
   ⬢       // Exit conditional
   ↓
   ●       // Exit
```
_There are two possible paths our code can take based on the flow..._

The above (_when created in a correct way_) is called a [Control flow graph](https://en.wikipedia.org/wiki/Control-flow_graph) and helps us visualize the flow of our program as a graph.

## Into the Complexity
By adding more conditionals or other control flow statements to our abstractions, the paths of execution that our code might take naturally increases.
As humans with minds that can hold up finite amounts of information at any point in time, it becomes much more difficult to reason about the expected outputs of a function when there are many paths the flow can take.

In simple terms __this is Cyclomatic Complexity. The independent flow paths that our abstraction can take while executing__.

Let's look at some JavaScript examples next, but the same terms apply to most programmings languages we use these days.


### Some examples

Let's start with the scenario that we are working on an ecommerce store and we are creating the function to calculate and return the price of a product based on some current state.

```javascript
/* Warmup */
function getPrice(currentState){
   const results = calculatePrice(currentState);
   return results;
}
```
__Cyclomatic Complexity : 1__
_Pretty simple, one path function. No conditional logic, so no additional paths to be generated_

```javascript
/* Single conditional */
function getPrice(currentState){
   if(currentState.loaded){
      return calculatePrice(currentState);
   }
   return 0;
}
```
__Cyclomatic Complexity : 2__
_Single conditional logic. Now depending the application state being loaded we return an actual result or 0. So one path for the case of loaded being true and one more path for the case of loaded being false._

Now we are asked to return also 0 when the customer is a guest, so the "first thing" would be to go with something like:

```javascript
/* Single conditional, two conditions */
function getPrice(currentState){
   if(currentState.loaded && !currentState.isGuestSession){
      return calculatePrice(currentState);
   }
   return 0;
}
```
__Cyclomatic Complexity : 3__
_Now this starts to get a bit more complex. You might be wondering why this results to Cyclomatic Complexity of 3, even if this function has only two possible outputs and a single conditional statement._

Unwrapping the above code we can see that the __&&__ operator can be also interpreted in this case as:
 ```javascript
/* Multiple conditionals, single condition */
function getPrice(currentState){
   if(currentState.loaded){
     if(!currentState.isGuestSession){
      return calculatePrice(currentState);
     }
   }
   return 0;
}
```
Now you may have a clearer picture of the "possible paths" that the execution can take and lead up to 3 unique.

*Remember that in order to reason about the output of this function you have to keep in your head 1) If the state is loaded, 2) If the session is that of a guest and 3) What this function is possible to return. Pretty much for a busy person if you ask me.

### Verdict

I hope you are starting to get a rough understanding why increased Cyclomatic Complexity might make it harder for software engineers to reason about their code and expected outputs. 
In my experience, when encountering code with relatively high Cyclomatic Complexity, there are many more things going on under the covers:
- Low test coverage
- Absence of Design Patterns
- "Speed over Quality" project conditions

### Feeling better

Congratulations on making it this far! I am pretty sure you might have learned something new or at least refreshed your understanding on Cyclomatic Complexity.

Calculating the Cyclomatic Complexity of an abstraction might be nice for practise in simple functions but our day to day interaction probably have to do with much more complicated constructs. Trying to figure out each functions Cyclomatic Complexity by going over it one by one, sounds a daunting task and not so much "time-well spent". But there are some steps you can take and make your life much easier!

## Now what ?

Another really surprising fact that I learned as I was researching this topic, was that one of the most used linting tools for JavaScript, ESLint, has a [Cyclomatic Complexity rule](https://eslint.org/docs/rules/complexity) by default!

By adding the rule in your ESLint configuration file, you can now inspect and report the Cyclomatic Complexity of functions on your codebase.
__Please start with something lax like 8-9 and start lowering as you go.__
```javascript
  "rules": {
    // ...
    "complexity": [2, 8]
  }
```
Now every function that has a complexity more than 8 will be reported by the linter. Even better, if you text editor has a plugin or integration with ESLint (like [vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)), you can now see the warnings as you are navigating over your files.
![ESLint warning on code](https://dev-to-uploads.s3.amazonaws.com/i/9brzdpec0bq3m4g79a33.gif)

### Some more tools

As our ability to reason about our code and prioritizing it on the projects we are working on is one of the most commonly discussed topics among peers, there are some more tools to help you to recognize, facilitate and consistently check Cyclomatic Complexity and other metrics:
1. [complexity-report-html](https://github.com/igneel64/complexity-report-html) A library which allows you to get a report of the current state of your JavaScript codebase with metrics like Cyclomatic Complexity. (Shameless plug!)
2. [Code Climate](https://codeclimate.com/) Much more sophisticated tool with many features including code complexity analysis.
3. [CodeScene/Empear](https://empear.com/) Visualization of code metrics and predictive analysis.



For any comments, feedback or just something you want to discuss, you can hit me up here on DEV or on any of my social platforms. Cheers!