0

I have an if statement set up like this

if (A && B) {
   // do something 1
} else {
   if (B) {
      // set some boolean to false
   } 
   // do something 2
}

I'm wondering if I can lower the cognitive complexity? Right now this is a score of 4.

aspiringsomeone
  • 535
  • 2
  • 9
  • 18
  • 2
    kind of a toy question: depends entirely on what the actual "do something"s are. Nesting conditionals might not even be the right choice for call routing at all. – Mike 'Pomax' Kamermans Jul 27 '21 at 21:33
  • 1
    I don't think it's possible to reduce complexity. With 2 boolean variables, you always have 4 different code paths. – Bergi Jul 27 '21 at 21:52
  • What tool do you use to get a score of your code complexity? It would be interesting to know - maybe add that to the question – Grazerbeam Jul 28 '21 at 00:06

5 Answers5

0

Well you could have only one level of depth like this:

function originalImplementation(A, B) {
  if (A && B) {
    console.log("do something 1");
  } else {
    if (B) {
      console.log("set some boolean to false");
    }
    console.log("do something 2");
  }
}

function newImplementation(A, B) {
  if (A && B) {
    console.log("do something 1");
  }
  else if (B) {
    console.log("set some boolean to false");
  }
  if (!A || !B) {
    console.log("do something 2");
  }
}

console.log("originalImplementation");

originalImplementation(0, 0);
originalImplementation(0, 1);
originalImplementation(1, 0);
originalImplementation(1, 1);

console.log("newImplementation");

newImplementation(0, 0);
newImplementation(0, 1);
newImplementation(1, 0);
newImplementation(1, 1);
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • 2
    This is not the same, `// do something 2` is also called on `if (B)` – Keith Jul 27 '21 at 21:44
  • 1
    No, this is not – Davedude Jul 27 '21 at 21:50
  • Update is much better,. debatable if `(!A || !B)` reduces cognitive complexity though :).. – Keith Jul 27 '21 at 22:11
  • I actually don't know how cognitive complexity is being calculated. Does the "complex" condition compensate the removal of the nesting? – Guerric P Jul 27 '21 at 22:15
  • I believe cognitive complexity is how the human brain sees it as been complex, I believe your original answer was nearly there, and is the reason I quoted your original answer in mine. Functions by definition are great for reducing cognitive complexity, so all I did was handle the double `do something 2` using a function. – Keith Jul 27 '21 at 22:20
0

Setting the boolean first can setup a clearer if/else

if(!A && B) {
  // set some boolean to false
}

if (A && B) {
  // do something 1
} else {
  // do something 2
} 

Another strategy is to drop out of functions asap

e.g.

if(X) {
  // do stuff

  return;
} 

if(Z)
{
  // do different stuff
  return; 
}

// do default stuff
return;

This allows the reader to dismiss logic beyond the condition they are interested in

Finally you can also create functions with meaningful names rather than comments

if(X) {
  return doSomething2();
} 
Grazerbeam
  • 345
  • 4
  • 17
0

I would say the best way to lower the cognitive complexity is to use functions. This is similar to @GuerricP original answer, but handles the multiple case of do somthing 2

eg.

function doSomething2() {}

if (A && B) {
  // do something 1
} else if (B) {  
  // set some boolean to false
  doSomething2();
} else {
  doSomething2();
}

This reduces complexity, because it's not obvious that there are 2 routes to doSomething2 in your original version.

Keith
  • 22,005
  • 2
  • 27
  • 44
0

I think this is the right way to do it and the cleanest.

const DoSomething = function(){}

if (A && B) {
} 
else if (B) {  
DoSomething();
} 
else {
 DoSomething();
}

0

Assuming you do one and only one thing for each case you can try decluttering the syntax:

  1. One-liner if statements don't need the curly braces
  2. You can avoid if, else if, etc. with an early return
const run = (a, b) => {
  if (a && b) return fun1();
  if (a) return fun2();
  if (b) return fun3();
  return fun4();
}

In this case I prefer using nested ternaries. Something usually considered as "bad practice" by tool makers and opinion leaders in the industry but I think with the right indentation they offer more decluttering opportunities:

const run = (a, b) =>
  ( a && b ? fun1()
  : a      ? fun2()
  : b      ? fun3()
           : fun4());

Of course YMMV ;)

customcommander
  • 17,580
  • 5
  • 58
  • 84