Home:ALL Converter>What are the pros and cons of replacing a list of conditionals(if/switch/ternary operators) with a predicate list?

What are the pros and cons of replacing a list of conditionals(if/switch/ternary operators) with a predicate list?

Ask Time:2017-03-22T17:56:04         Author:DoubleX

Json Formatter

Recently I've come across with a school of thought that advocates replacing conditionals(if/switch/ternary operators, same below) with something else(polymorphism, strategy, visitor, etc).

As I'd like to learn by trying new approaches, I've then revised some of my Javascript codes and immediately found a relevant case, which is basically the following list of ifs(which is essentially the same as a switch/nested ternary operators):

function checkResult(input) {
    if (isCond1Met(input)) return result1;
    if (isCond2Met(input)) return result2;
    if (isCond3Met(input)) return result3;
    // More conditionals here...
    if (isCondNMet(input)) return resultN;
    return defaultResult;
};

Shortly after I've come up with trying a predicate list instead.

Assuming that checkResult always return a String(which applies to my specific case), the above list of ifs can be replaced with a list of predicates(it uses arrow function and find which are ES6+ features though):

var resultConds = {
    result1: isCond1Met,
    result2: isCond2Met,
    result3: isCond3Met,
    // More mappings here...
    resultN: isCondNMet
};
var results = Object.keys(resultConds);

function checkResult(input) {
    return results.find(result => resultConds[result](input)) || defaultResult;
};

(On a side note: Whether checkResult should take resultConds and defaultResult as arguments should be a relatively minor issue here, same below)

If the above assumption doesn't hold, the list of predicates can be changed into this instead:

var conds = [
    isCond1Met,
    isCond2Met,
    isCond3Met,
    // More predicates here...
    isCondNMet
];
var results = [
    result1,
    result2,
    result3,
    // More results here...
    resultN
];

function checkResult(input) {
    return results[conds.findIndex(cond => cond(input))] || defaultResult;
};

A bigger refactoring maybe this:

var condResults = {
    cond1: result1,
    cond2: result2,
    cond3: result3,
    // More mappings here...
    condN: resultN,
};
var conds = Object.keys(condResults);

function checkResult(input) {
    return condResults[conds.find(cond => isCondMet[cond](input))] || defaultResult;
};

I'd like to ask what're the pros and cons(preferably with relevant experience and explanations) of replacing a list of conditionals with a predicate list, at least in such cases(e.g.: input validation check returning a non boolean result based on a list of conditionals)?

For instance, which approach generally leads to probably better:

  • Testability(like unit testing)
  • Scalability(when there are more and more conditionals/predicates)
  • Readability(for those being familiar with both approaches to ensure sufficiently fair comparisons)
  • Usability/Reusability(avoiding/reducing code duplications)
  • Flexibility(for example, when the internal lower level logic for validating inputs changes drastically while preserving the same external higher level behavior)
  • Memory footprint/Time performance(specific to Javascript)
  • Etc

Also, if you think the predicate list approach can be improved, please feel free to demonstrate the pros and cons of that improved approach.

Edit: As @Bergi mentioned that Javascript objects are unordered, the ES6+ Maps may be a better choice :)

Author:DoubleX,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/42948150/what-are-the-pros-and-cons-of-replacing-a-list-of-conditionalsif-switch-ternary
Bergi :

In general, putting business logic (like these predicates) in separate objects always improves testability, scalability, readability, maintainability and reusability. This comes from the modularisation inherent to this OOP design, and allows you to keep these predicates in a central store and apply whatever business procedures you want on them, staying independent from your codebase. Essentially, you're treating those conditions as data. You can even choose them dynamically, transform them to your liking, and work with them on an abstract layer.\n\nReadability might suffer when you need to go to certain lengths to replace a simple a short condition with the generic approach, but it pays of well if you have many predicates.\n\nFlexibility for adding/changing/removing predicates improves a lot, however the flexibility to choose a different architecture (how to apply which kind of predicates) will worsen - you cannot just change the code in one small location, you need to touch every location that uses the predicates.\n\nMemory and performance footprints will be bigger as well, but not enough to matter.\n\nRegarding scalability, it only works when you choose a good architecture. A list of rules that needs to be applied in a linear fashion might not do any more at a certain size.",
2017-03-23T02:34:36
yy