DEV Community

Cover image for How to eliminate if-else chain, for long life software
Sameh Muhammed
Sameh Muhammed

Posted on • Updated on

How to eliminate if-else chain, for long life software

Motivation

All programing principles and paradigms aim to enhance code readability and maintainability, from OOP to functional, SOLID, DRY, YAGNI, KISS and design patterns all these main purpose is to write clean and maintainable code for long life software, as a software by nature will keep evolve and change, so all these concepts help us to make our software flexible and easy to change.

Boost readability and maintainability

One of most popular code smell is if-else chain or code branching, of course you can't develop a software without if-else but heavily using to harms your code and in order to eliminate/reduce multiple is-else chain there are some tactics you can do to avoid this code smell.

Fail early mechanism

This mechanism works by validate violation first and terminate if any violation happen, instead of checking for right values and terminate if not as below

Image description

Flat-Chain mechanism

This mechanism works by repeating your conditions over if statements to avoid branching in your code and this approach favoring readability over performance if code may be need a lot of changes in future

Image description

Use polymorphism

If you have multiple operations and you need to fire specific one depending on specific condition, you can encapsulate creation of these operations into one single class(Factory) and delegate the determination of what operations fit for this criteria to one isolated place and make your code more readable and this make code strict to open-closed principle.

Image description

Predicate-Action mechanism

You can apply this mechanism by using a Map or List of Pairs one side is a predicate(condition) and the other side is the action you want to fire if the predicate success and by iterating over this pairs you can achieve your conditional logic in better way

Image description

Use State design pattern

By using this you first define your states as below

Image description

Then implementing each state and which state currently now and which state you are allowing to return from current one.

Image description

Image description

Then use the states with your object

Image description

Demo project for all tactics

IF YOU LIKED THE POST, THEN YOU CAN BUY ME A COFFEE, THANKS IN ADVANCE.

Buy Me A Coffee

Top comments (30)

Collapse
 
jmfayard profile image
Jean-Michel (jmfayard.dev)

Agree with all your points.

Language specific, but in Kotlin the when expression is a massive improvment over if/else

val message = when (x) {
    in 1..10 -> "x is in the range"
    in validNumbers -> "x is valid"
    !in 10..20 -> "x is outside the range"
    else -> "none of the above"
}
println("validate($x): $message")
Enter fullscreen mode Exit fullscreen mode
Collapse
 
smuhammed profile image
Sameh Muhammed

Yes, good tip but i don't use Kotlin that much, it's language specific but the idea is to make code more readable.

Collapse
 
jmfayard profile image
Jean-Michel (jmfayard.dev)

I wonder what other languages have a similarly good structure.
Not like switch case which don't return anything, something better.
Probably functional languages in general?

Thread Thread
 
alexmario74 profile image
Mario Santini

Like switch expressions for Java v12 have a look

Thread Thread
 
jmfayard profile image
Jean-Michel (jmfayard.dev)

indeed yes, I didn't know they can return a value

Thread Thread
 
xfbs profile image
Patrick Elsen

Rust has a nice match statement too, even though it is not functional.

match person {
    Person::Employee(employee) if employee.years() > 3 => true,
    Person::Employee(employee) if employee.age() >63 => true,
    Person::Intern(internet) if intern.name().first() == 'S' => true,
    _ => false
}
Enter fullscreen mode Exit fullscreen mode

I believe it is something that most functional language have and newer languages are starting to adopt it.

Thread Thread
 
delta456 profile image
Swastik Baranwal

Almost every modern language have pattern matching.

Thread Thread
 
jmfayard profile image
Jean-Michel (jmfayard.dev)

Tree patterns are used in some programming languages as a general tool to process data based on its structure, e.g. C#,[1] F#,[2] Haskell,[3] ML, Python,[4] Ruby,[5] Rust,[6] Scala,[7] Swift[8] and the symbolic mathematics language Mathematica have special syntax for expressing tree patterns and a language construct for conditional execution and value retrieval based on it.

In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. In contrast to pattern recognition, the match usually has to be exact: "either it will or will not be a match." The patterns generally have the form of either sequences or tree structures. Uses of pattern matching include outputting the locations of a pattern within a token sequence, to output some component of the matched pattern, and to substitute the matching pattern with some other token sequence.

Thread Thread
 
n1ckdm profile image
Nick

The techniques above are called pattern matching. I wrote an article about it here:
dev.to/n1ckdm/pattern-matching-dec...

Thread Thread
 
jmfayard profile image
Jean-Michel (jmfayard.dev)

Really good article thanks
Not that Kotlin when is not true pattern matching found in more fiftieth languages, it's a better switch case. Combined with static types and algebraic types it's 80% of that though

Thread Thread
 
matthewbdaly profile image
Matthew Daly

Newer versions of PHP have match.

Collapse
 
moopet profile image
Ben Sinclair

Just a heads up that the Markdown we use here supports syntax highlighting, and is generally more accessible than inserting an image of code. Images of text are an issue for people using screen readers, for example, and their content won't get picked up by the site's search facility.

You can add code blocks with 3 backticks: code block with colors example More details in our editor guide!

Collapse
 
smuhammed profile image
Sameh Muhammed

Thanks! , great idea

Collapse
 
rob84 profile image
Robert

I would say be aware of polymorphism. It's not wrong, but not the only concept.
The principle composition over inheritance is often a better choice, because you don't couple classes with an inheritance structure.
Sometimes it's a great mix to use inheritance for the structure and composition for the logic.

Collapse
 
peerreynders profile image
peerreynders

Sometimes it's a great mix to use inheritance for the structure and composition for the logic.

i.e. prefer interface inheritance (implements; for polymorphism) over implementation inheritance (extends).

The original quote (GoF, 1994, p.20):

Favour object composition over class inheritance

talks about implementation inheritance.

Collapse
 
smuhammed profile image
Sameh Muhammed

Actually, we talked about this principle here Composition vs Inheritance, take a look 😉

Collapse
 
juanvegadev profile image
Juan Vega

Good post.

Just to add something, there is another possible iteration when you have a set of fixed conditions (like the switch), for large number of options a map is a better and more readable approach.

Collapse
 
turowski profile image
Kacper Turowski

I am SOOOO HAPPY to see your article. For once it's "how to do it better" and not "omigosh, you should NEVER nest if-s, here's why". Glad to see people who don't clickbait.

Collapse
 
smuhammed profile image
Sameh Muhammed

Your comment made me happy also 😄,
You can follow me for more amazing content, and stay tuned 😉

Collapse
 
turowski profile image
Kacper Turowski

Such humility too, hahahaha! 😁

Thread Thread
 
smuhammed profile image
Sameh Muhammed

😃😃😄

Collapse
 
hngvchnh1 profile image
Hưng Võ Chánh

nice

Collapse
 
fabestah profile image
fabestah

Great read 💯

Collapse
 
terrydiana profile image
Terry-Diana

This is a good tip

Collapse
 
mcsee profile image
Maxi Contieri

amazing post !

Collapse
 
marcello_h profile image
Marcelloh

In the Fail early, the final result of your change is not the same.
Because it should fail at a negative price or a discount equal or higher than 50.

Collapse
 
smuhammed profile image
Sameh Muhammed

Yeah, but it just example that helps illustrate the idea not more