Avoiding if-else Hell: The Functional Style
lackofimagination.org
lackofimagination.org
>Instead of hardcoding the logic inside our function, we can place each if-else block in its own function and put those functions in an array, forming a decision table.
In my experience this is always an unwelcome addition to a codebase and a worse choice than just several lines of ifs
* You've added a level of indirection
* You've written the code in a less straightforward way, your fellow programmer might now need to spend more time understanding what they're looking at and wondering why you wrote it like that instead
* The ifs are still there, it's not inherently simpler just because it's tucked away
* They could've been tucked away in functions, which have the benefit of having names, making them (maybe) a bit more self-explanatory?
But most importantly
* You've introduced an abstraction, and it might be the wrong one
What if one of the conditions need to have a different kind of follow up?
Some people then build two separate decision tables depending on what the follow up needs to be, some take the outstanding "if" out of the decision table and add it back in the regular control flow, which kind of highlights the problem on its own, but...
Some other people double down and make the decision table a more robust abstraction, and in my opinion this is the worst outcome. You end up with some bullshit Predicate & PredicateEngine, callbacks, why not maybe async, and at that point you need to look at it and realize "We're making a framework, and we will eventually need to extend it until it encompasses the entire possibilities of the language's control flow, except with massive overhead, and nothing of value being created"
// Original
if a
if b
else
else
if b
else
// New
if not a and not b
if not a and b
if a and not b
if a and b async function assignDriver(rider, availableDrivers) {
const driverDistances = await calculateDistances(rider.location, availableDrivers);
for (let driver of availableDrivers) {
if (driverDistances[driver.id] > 5) {
continue;
}
if (rider.preferredVehicle && rider.preferredVehicle !== driver.vehicle) {
continue;
}
if (driver.rating < 4.0) {
continue;
}
if (driver.rating >= 4.5 && rider.preferences.includes('Premium Driver') && !driver.isPremiumDriver) {
continue;
}
return driver;
}
return null;
}Example. Is there something wrong in the following statement? You don´t know, because it does not specify what the intended meaning of the statement is.
if (foo.a <= 3 && bar || bar > 34 && ( ...etc ))
Take away: break up the parts of you logical condition, give them a name, reassemble the condition from the logically named parts. A a rule of thumb, a condition that reads like a regular sentence is a clear condition.Notice that the author didn’t explain how the nested IF ELSE form worked. That’s because we all know how it works. It’s dirt easy. There is a lot to be said for programming in a way that is familiar and plain.
Yes, there are clever alternatives, but most of them require more time to stare at them and work out what is happening.
Computer programs are hoards electric voltages changing to discrete levels at fixed intervals to create interesting and coordinated effects on surrounding devices.
Computer programs are 0-N statements of expressions to evaluate.
Theres 2 perspectives completely devoid of “if.”
Just lovely. For some reason, rust and ocaml added ifs even though they have match. In rust if-let has orthogonal value, but id happily live without it for less syntax
And thanks, I've been trying to get my team to get used to writing `else`-less code (i.e., without nesting as much as possible), I'll keep your link in my bookmarks and share it with them when appropriate.
When I have some complex logic to deal with a draw a state diagram and build my if statements based on that.
I have fixed a lot of bugs due to "elseif" over the decades in various languages. The person who came up with that construct should endure the Confy Chair.
If we didn't have else-if, somebody will certainly lament "If we had something called else-if, I'd not have fixed a lot of bugs due this complex condition statements in various languages. The person who opposes implementation of such a simple construct should endure the Confy Chair".
So, it goes both ways.
Moreover, else-if is probably the most misused conditional, so while I disagree that it shouldn't exist (it has some uses), GP has a point.
Although linters now are good enough now to catch poorly used conditionals, so his point is way less relevant than it was a decade ago.
Depends on the code base and problem domain you code / live in. In most cases you're right, but in my domain it's a different story.
> Moreover, else-if is probably the most misused conditional
You can misuse anything in any language, so by this logic we should argue that we shall abolish all programming altogether. I can misuse threads to make a program slower, misuse memory allocator to fragment the memory, etc. etc.
So I don't think "but people misuse it" is a great argument either.