Neural complexity and nesting: 3 practical tips

Johan Book
3 min readDec 16, 2022

When reading code it should be like reading any other language, it should be close to effortless. However, there are some things that can hinder that. One of the easier thing to look for is to minimize nesting in code.

The measure for how difficult a piece of code is to parse for the human brain is called neural complexity. One thing that has a big impact on neural complexity, is the number of things you need to keep in mind simultaneously. Reading code with functions that are over several hundreds of lines with countless variables, is not fun because it requires a high effort. In other words, it has a high neural complexity.

One thing that will always increase neural complexity is nesting in code, because you per definition need to keep the outer scopes in mind. To improve this, I argue to avoid nesting where ever possible. In this article I will give 3 concrete examples of how to decrease nesting, and hopefully, produce some cleaner code.

Avoid unnecessary else clauses

One common example is to return from an else statement when this branching in fact is redundant. Consider the following example:

/** Example */
function extractData(data) {
if (data.total > 42) {
return data.elements.a;
} else {
return data.elements.b;
}
}

/** Improved */
function extractData(data) {
if (data.total > 42) {
return data.elements.a;
}

return data.elements.b;
}

What is the difference between the two examples? In the second example you need to keep the condition in mind for both branch paths, while it is not needed. That is we have escaped a little nesting.

Avoid nested conditionals

One easy mistake to do, is to perform multiple layers of nested if statements. This is especially common when doing switch style checks (where actual switch statements are not applicable). However, often this can be refactored to to avoid nested conditional statements — typically by doing negative checks instead of positive ones. For example, consider the example below.

/** Example */
function checkForErrors(data) {
if (data) {
if (data.error) {
return data.error;
}

if (data.length == 0) {
return "Elements are required in data but not found";
}

return true;
}

return false;
}

/** Improved */
function checkForErrors(data) {
if (!data) {
return false;
}

if (data.error) {
return data.error;
}

if (data.length == 0) {
return "Elements are required in data but not found";
}

return true;

}

Example 2 is easier to read, because it removes one layer nesting. Keep this in mind when coding, where can we remove redundant nesting?

Move nested code to their own functions

Sometimes nesting cannot be avoided, however, it is still possible to decrease the neural complexity by moving nested code to their own functions. See the following example:

/** Example */
function createPointsFromData(data) {
const points = [];
for (const outerPoint of data.points) {
for(const innerPoint of outerPoint.neighbors) {
const newPoint = {point: innerPoint};

// This nested logic is difficult to read
if(innerPoint.value < outerPoint.value) {
newPoint.index = ...
}

points.push(newPoint);
}
}

return points;
}

/** Improved */
function createPoint(outerPoint, innerPoint) {
const newPoint = {point: innerPoint};

// This separate function is easier to read
if(innerPoint.value < outerPoint.value) {
newPoint.index = ...
}

return newPoint;
}

function createPointsFromData(data) {
const points = [];
for (const outerPoint of data.points) {
for(const innerPoint of outerPoint.neighbors) {
const newPoint = createPoint(outerPoint,innerPoint;
points.push(newPoint);
}
}

return points;
}

Note that this approach also helps writing functions that more clearly have a single responsibility — which the unimproved example failed at.

--

--

Johan Book

I am a frontend engineer who likes to dabble in philosophy, AI and IT security