How to Escape the If Inception

Yini Yin
4 min readApr 26, 2020

--

Some Say If is Evil

In Robert Martin’s book Clean Code he explains why if statements are considered harmful and suggests when there is an awful amount of if statements in our code, it usually indicates the underlying nature of the problem is polymorphic. I am not going to discuss why if statements considered harmful here, you can read an excellent article by Jetbrains about the problem if statements could bring if you are interested.

I do see the point as in why excessive amount of if statements are a terrible situation to be in. I don’t however, quite agree on that polymorphism underpins the problem at hand. Sometimes we could indeed refactor out of a sea of if statements with polymorphism — subtype or inclusion polymorphism to be specific. Other times I feel this is too heavy handed because some scenarios are just too simple to warrant subtype polymorphism which is one of the strongest couplings in OO and it is not hard to get wrong!

Let’s take a look at an example below:

Applying polymorphism in cases like this is just way over engineering and I would argue it is worse than if statement! But it is just a ton of if-else, it is simply noise and careless duplications!

Let That Be a Pattern

The same code above can be rewritten as below and see how compact, yet how expressive it is! And yes, we pass that ignore case comparer into it!

Fold knowledge into a clever data structure so our program can be as dumb as possible!

It is surprising how easy it is for our brain to unpack the knowledge captured in data table! Essentially data table implies correlation, i.e. if it is A then I want X, if B then I want Y, etc. You see the ifs there? So I call it The Dictionary Pattern.

What Else this Dictionary Pattern is good at?

Some blog posts compare Rest API vs Graphql, claim that Rest API has one endpoint per resource whereas Graphql only one endpoint for all. This is simply not true. For a start, Graphql has two endpoints: query and mutation. Query for GET and mutation for both PUT and POST as Rest equivalence. And for Rest API, indeed most people would have three endpoints (GET/PUT/POST) for each and every resources. So if we have three resources, we could have up to nine endpoints.

Here is what a verbose Rest controller would look like. Every single resource has its own GET route.

In the service that serves up the controller, quite often we need to do some prerequisite check before we serve up the data e.g. check if customer is under aged, check if customer subscription has expired, etc. Of course we repeat these prerequisite checks for each every one of the endpoints we serve, which I have seen a lot in real production code. So imagine we have three resources (Thor, Ironman and Thanos) we do GET/PUT/POST on, then we have nine endpoints, so we repeat these checks nine times! Here below shows what service might look like:

Let’s apply Dictionary Pattern. I only demonstrate GET, but the same principle goes for PUT and POST. Here below are the three endpoints our Rest API ever need for all resources so long as we design your data structure right!

In service, we create a Resolvers of dictionary<Enum, Func> type. Its key is the string enum of a route name, and the value is a function delegate that serves up that particular route.

We are able to reduce controller code quite a bit. And although the amount of code in the service has been reduced but not as significant as compared to controller. The reason is, just as in graphql’s resolvers, each graphql resolver has to be specifically written out to serve a particular schema query or mutation, so does Rest API! There is no free lunch, someone, in somewhere has to do the work!

So With Dictionary Pattern we get:

A much cleaner, smaller controller — one endpoint for all GET queries!

A clean separation between route serving relaying and computation logic in the service layer.

A gateway method that we run common logic e.g. security check, data sanitisation, customer eligibility check, etc.

Closing Note

The Dictionary Pattern I describe here is neither a law you have to abide, nor a disapproval of if-statement. It is simply a different way of thinking about condition and correlation.

As always, thank you for your time. I hope you find it useful and would be keen to know what other scenarios you use it in your projects.

Reference

Source code used in this article

Code Smells: If Statements

Polymorphism without Inheritance

On Understanding Types, Data Abstraction, and Polymorphism

--

--

Yini Yin
Yini Yin

Written by Yini Yin

Try not to be a jack of all trades always end up being one. Dev@Barin

No responses yet