A Developer's Journey to solve real-world problems

Why I prefer map over multiple if-else?

Problem Statement

Everybody uses switch(if-else) statements in development. However, there are cases where multiple switch conditions can cause redundancy, and using a map provides extensibility. A very generic case is when we are calling different handlers for different cases but all handlers implement the same interface. For example - The server wants to send a notification via SMS, Facebook, or Slack based on input. Treat this as pseudocode.

class SMSNotifier(NotifierInterface):
    def sendMessage(msg):


class FacebookNotifier(NotifierInterface):
    def sendMessage(msg):

class SlackNotifier(NotifierInterface):
    def sendMessage(msg):


#Implementation
if (source=="SMS"):
    SMSNotifier().sendMessage(msg)
elif (source=="Facebook"):
    FacebookNotifier().sendMessage(msg)
elif (source=="Slack"):
    SlackNotifier().sendMessage(msg)

This is a very simple case.

Solution

There is no problem as such with the previous implementation based on the design principles. There are much worse ways to write the code without implementing the interface. What I figured out was I can even reduce the interface-based redundancy using maps.

The map

What my map stores is the mapping of source values to the corresponding interface to be used.

source_notifier_map = {
  "SMS": SMSNotifier,
  "Facebook": FacebookNotifier,
  "Slack": SlackNotifier
}

The code

Let's look at the implementation with the defined map.

#Implementation
notifier = source_notifier_map.get(source)
notifier().sendMessage(msg)

Advantages:

Disadvantages:

Potential Overuse

I can potentially extend this behavior to all if-else statements using functions. Functions are not supposed to follow a single interface. I just need to take care of function parameters to be consistent across all cases.

def function1(source):

def function2(source):


if (source==case1):
   function1(source)
elif (source==case2):
   function2(source)

can be replaced with

case_function_map = {
  case1: function1,
  case2: function2
}

#implementation
function = case_function_map.get(source)
function()

Why shouldn't we use this?

If the logic across functions function1 and function2 are not the same, developers who are reading will not understand the piece of code in #implementation. The abstraction created using map will create confusion if the abstraction doesn't follow a single interface.

So, I would only use this abstraction if all the cases follow the same internal interface. In fact, don't use functions to implement such abstractions. Always use classes following an interface.

Footnotes:

Map data structure

I think everybody knows what a map data structure is. Just a reiteration. Map data structure is a type of data structure that stores associations between keys and values. It is a collection of key-value pairs, where each key is unique and is associated with a single value. Maps are often used to store data organized by key, allowing for fast look-up of the associated value. Python defines map as:

d = {
   "key": "value"
}

#development #programming