code-like-a-pro-stop-using-more-than-one-else-if-statement
Sometimes, the ‘less is more’ saying can perfectly describe coding. Or efficient coding, if you will. That’s why, I highly recommend you stop using more than one ‘else-if’ statement. But let me elaborate.
In many situations you will have to map from one value to another from a known set. You could get an Enum that needs to be mapped to a string, or an API that provides a string value that must be mapped to a number.
When it comes to more advanced situations, you must do different processing tasks based on the value of a variable. Blocks of code similar to the one below are surely familiar to you. Am I right?
How many times have you stumbled upon this scenario?
It may look fine, and it’s certainly easy to understand, however, it is not the right way of doing things. What happens if the conditional is not from the ones in the method? Or what happens if a few months after development 5 new values appear, and you must handle them all separately?
You could wind up having even more ‘else-if’ statements. My take on this issue is that, sooner or later, this approach will result in a series of long and complicated methods that are hard to maintain. And why bother, when you have simpler alternatives available.
Let’s look at some better ways of handling these situations.
One way of coding like a pro is to always look for the simplest way possible to achieve the results you want. Writing more code doesn’t mean that it will always work better. In fact, you could be creating more space for future errors to pop up. Which brings us to my next point.
Instead of having ‘if’ and ‘else-if’ statements to determine what is the processor, it will be easier to have it directly in the Enum. This way, when a new value in the Enum is added, you will automatically know how to handle it.
You have an interface, let’s call it Processor, that holds the definition for all processors, and concrete implementations: Processor1, Processor2, and Processor3. Next, let’s have the Enum values register each processor that corresponds to them:
Now you can completely remove the ‘if’ statements and instead get the processor from the supplied value:
If you want to have a new instance of each processor instead of reusing the same one, you can make it so that a factory exists for each of them and the getProcessor() method constructs a new instance.
The above approach works well when you are dealing with Enums that only have one processor assigned or one other value mapped to them. However, what happens if we encounter a more complex logic for each?
Let’s assume that this Enum is used in several places throughout the code. In one location it’s used to get a processor based on the value. In another to return a numerical value that is associated with it. In a third location the value is used to call different services and so on.
Sure, you could have the constructor for the Enum hold all the needed data, the processor, the numerical mapping and the service that needs to be called. Unfortunately, this approach will complicate things fast and will make maintaining the Enum harder. Also, just like before, what happens if this Enum will be used in even more places as the code evolves?
Let me propose a better way of doing things.
In each location where you need to go from one Enum value to something else, you create a Map that holds the Enum value as the key and the processor/numerical value/service as the value. Ideally, you could make this map immutable (using Guava ImmutableMap Builder), but it should be at least static and final to save up on space and to reduce possible errors.
In the other locations you can have something similar that maps between the values of your Enum and other needed values.
Next, you need to get the processor and call it:
The same approach can be used even when you don’t have Enums, but other data type where the first method can’t even be used. You can as easily have a Map with String as the key or even an Integer.
This method has one disadvantage though. If later on you’ll need to add new values for your Enum, you’ll have to change the Map in multiple files. Still, this will only be needed if a processor or a mapping for the new value is required.
You could just as easily have MyEnum.VALUE4 for which no processing needs to be done, but it should be mapped to an Integer along with the rest. Now, you’ll only be changing the Map for the integers, without ever touching the Map for the processors.
And that’s pretty time efficient if you ask me.
‘If statements’ are an essential part of all applications. Life without them would be much more complicated. However, if you have too many of them one after another, the implementation of your method should be changed.
Always search for “the shortest road possible” when it comes to coding. That’s how the pros do it.
Hopefully the two different approaches I provided will help you out. Choose the one that best suits your needs, and let me know how it went!