🚫 Stop using SWITCH, please 🙏
Ivan Zaldivar
Posted on April 4, 2023
If you're a software developer, chances are you'll use the switch
stament at some point. This operator allows you to evaluate the expression and execute different blocks of code depending on the value of said expression. Although switch is a useful tool, overusing it can lead to code that is difficult to maintain and modify. In this article we explain why you should consider moving away from switch and some alternatives you can use to improve the readability and maintainability of your code.
Problem
In this example, the notifier function takes a notification argument of type Notification
, which is an enum representing different notifications. The function uses a switch statement to determine which notification to send based on the value of the Notification
argument. We see an example:
You can take a look at why it is not recommended to use Enums here
const enum Notification {
verifySignUp,
resendVerifySignup,
emailConfirmed
}
export function notifier (notification: Notification) {
switch (notification) {
case Notification.verifySignUp:
// Execute something...
return;
case Notification.resendVerifySignup:
// Execute something...
return;
case Notification.emailConfirmed:
// Execute something...
return
}
}
As the number of cases within the switch increases, the readability of the code suffers. Also, if a new fruit is added to the enum, the function must be updated to handle the new case, which can lead to errors if you forget to update it.
There are more scalable and maintainable alternatives to switch in this case, such as using an object that contains the colors of the fruits. This also makes the code more readable and scalable as more fruits are added.
Another possible alternative that I have found in other projects is the use of if.
export function notifier(notification: Notification) {
if (notification === Notification.verifySignUp) {
// Execute something...
return;
}
if (notification === Notification.resendVerifySignup) {
// Execute something...
return;
}
if (notification === Notification.emailConfirmed) {
// Execute something...
return;
}
}
But as you have to see, both have the same drawback. Now that we've come across the problem head-on. How do we improve this?
Solution
As in any software solution there are different implementations of how to solve a problem. In this case we are only going to address two, one of them is the use of objects
and the other is through mapping functions
Using objects
const notificationDirectory = {
verifySignup: () => {
// Execute something...
},
resendVerifySignup: () => {
// Execute something...
},
emailConfirmed: () => {
// Execute something...
}
}
type NotificationTypes = keyof typeof notificationDirectory
function notifier (notification: NotificationTypes) {
const handler = notificationDirectory[notification]
if (!handler) throw new Error("Your method does not exist");
if (!(typeof handler === 'function')) throw new Error("Your method must be a function");
// Execute your method
handler()
}
// send email for the user to confirm his email.
notifier('verifySignup')
// send email notifying that your email was verified
notifier('emailConfirmed')
Using Mapping Funtions
const notificationMap = new Map<string, () => void>()
notificationMap.set('verifySignup', () => {
// ...
})
notificationMap.set('resendVerifySignup', () => {
// ...
})
notificationMap.set('emailConfirmed', () => {
// ...
})
function notifier (notification: string) {
const handler = notificationMap.get(notification)
if (!handler) throw new Error("Your method does not exist");
handler()
}
The following details the advantages of using these techniques instead of switch:
Easier to maintain: As new notifications are added, there is no need to add more instances inside a switch statement, just add a new function to the
notificationDirectory
object.More flexible: you can add or remove notifications at any time without having to worry about updating the corresponding switch statement.
Safer: By using the
NotificationTypes
type, you can ensure that only valid values are passed to the notifier method. If an attempt is made to pass a value that is not one of the valid keys of thenotificationDirectory
object, a runtime error will be thrown. This can help catch bugs earlier.More scalable: Instead of writing a single long function that handles multiple different cases, this approach allows you to define a separate function for each case, making your code more modular and easier to read and maintain.
More efficient: In some cases, using a map instead of a switch statement can be more efficient in terms of execution speed. This is because maps are implemented as a key-value lookup data structure, which allows you to look up and retrieve values more efficiently than sequential lookup in a switch statement.
Conclusion
In conclusion, although the switch statement is a useful tool in software development, its excessive use can lead to code that is difficult to maintain and modify. As the number of cases within the switch increases, the readability of the code suffers, and adding new cases can lead to errors if you forget to update all the instances in which it is used. In addition, there are more scalable and maintainable alternatives, such as using objects
or mapping functions
, which can improve code readability and maintainability. Therefore, it is important to consider the proper use of the switch statement and evaluate other alternatives to improve code quality in software development.
Follow me
- 🐙 GitHub: https://github.com/thebug404
- 🐦 Twitter: https://twitter.com/thebug404
Posted on April 4, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.