I am refactoring a function with too many if-else's, something like the following but more complicated. Some major characteristics of this function are:
- It bails out early for many pre-conditions (e.g.,
condition1()andcondition2()). - It only does some meaningful stuff on very specific scenarios (e.g.,
doA()anddoB()). (Oh yeah, the beauty of temporary bug fixing!) - Some pre-conditions may or may not be independent of additional conditions (e.g.,
condition3/4/5/6()).
retT foo() { // total complexity count = 6
if (!condition1()) { // complexity +1
return retT{};
}
if (!condition2()) { // complexity +1
return retT{};
}
if (condition3()) { // complexity +1
if (condition4() || condition5()) { // complexity +2
return doA();
}
else if (condition6()) { // complexity +1
return doB();
}
}
return retT{};
}
The goal is to call out those actual works on their precise conditions rather than leaving them vulnerable to the change of the if-else structure in foo(). More specifically, I would like to turn foo() into something like this:
retT foo() { // total complexity count = 4
ConditionalCommand<retT> conditionalDoA{doA};
conditionalDoA.addCondition(condition1());
conditionalDoA.addCondition(condition2());
conditionalDoA.addCondition(condition3());
conditionalDoA.addCondition(condition4() || condition5()); // complexity +1
ConditionalCommand<retT> conditionalDoB{doB};
conditionalDoB.addCondition(condition1());
conditionalDoB.addCondition(condition2());
conditionalDoB.addCondition(condition3());
conditionalDoB.addCondition(!(condition4() || condition5())); // complexity +2
conditionalDoB.addCondition(condition6());
for (auto& do : {conditionalDoA, conditionalDoB}) {
if (do()) { // complexity +1
return do.result();
}
}
return retT{};
}
This makes the implementation more linear and the conditions for performing a particular work more explicit. I understand that it would be equivalent to just creating a first-level if-clause for each work with all the added conditions listed, but the above code would:
- reduce our internal complexity measurement (if-else, logical operators, and ternary based, as illustrated in the code comments),
- prevent future intrusion into the first-level if-clauses by a new developer, for example, who wants to
doC()instead ofdoA()ifcondition7()istrue, and - allow me to refine each work's conditions independently of those of the other works (recall that some conditions might be depending on each other).
So the question is, is there any existing std or boost utility that does what ConditionalCommand does so I don't need to reinvent the wheel?