6

This Programming Principle will Reduce if/else Statements

 2 years ago
source link: https://blog.bitsrc.io/reduce-if-else-switch-usage-with-this-programming-principle-8756358365cd
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

This Programming Principle will Reduce if/else Statements

Reduce if…else and switch statement usage by implementing better separation of concerns

1*rqeJOHAVfW8MUydYkD7FzA.jpeg

Photo by Joan Gamell on Unsplash

The if…else structure is one of the first patterns we come across when learning a programming language. It is simple, if a condition is true, do this, otherwise, do something else.

There is absolutely nothing wrong with using them. However, sometimes they can lead to writing code that is hard to maintain and expand.

Most of the time, their excessive usage will look like the following:

function doSomethingWithX(x) {if (x === 'A') {
// x equals 'A' logic
}
if (x === 'B') {
// x equals 'B' logic
}
if (x === 'C') {
// x equals 'C' logic
}
if (x === 'D') {
// x equals 'D' logic
}// Function's Logic after the if clauses
console.log(x)...

Whenever we want to add something new to this piece of code, we are going to have to include a new if statement to handle a new possibility.

In some cases, the amount of if statements may grow out of control. When there is a new requirement in our code, we are always going to have to include a new logic in some way. The idea of this article is to present an alternative that impacts our existing code the least.

Separation of concerns

In our example, the function doSomethingWithX was responsible for figuring out what it should do with x based on its value. Each case carries its logic, the function is responsible for handling all of them, as well as being able to differentiate when to use one or the other

What if we took away such responsibility from the inside the function and delegate it to something else?

In other words, we could assign each business logic contained inside an if statement to another entity in our code, cleaning our function to take care only of what comes after it, which is logging it to the screen in this simple example.

This is commonly known as the Single Responsibility Principle(SRP). Which states that:

An entity should have one and only one reason to change

To better understand the meaning of this principle. Let’s consider the following example in TypeScript of an online shop that we run, and we have to send e-mails based on the current order status:

The EmailService class has a method responsible for sending an e-mail to a customer. The sendOrderEmail method is responsible for differentiating which text and subject to use and sending the e-mail. Whenever we need to include a new Order State, we have to update the switch statement.

The single responsibility principle states that an entity(which can be a function, a method or a class) must have only one reason to change. Clearly, the example above does not follow this rule. Whenever we need to adjust something in the texts for any of those statuses, whenever we need to add new information to them or we need to change something in the sending of e-mails logic, we will have to modify the sendOrderEmail method. It means that there are several reasons that will force us to adapt this function.

Let’s refactor this code in a way that all these concerns are separated:

We turned the Order class into an abstract one and we have created four new sub-classes, each responsible for handling the logic of a different status. The method responsible for sending the email and the logic of choosing the e-mail text and subject are completely decoupled. The sendOrderEmail is no longer concerned by how it will choose or compose the e-mail subject or text, it is only concerned about sending it!

Implicit Usage of a Design Pattern

If you already have come across the topic of the Gang of Four’s Design Patterns, the solution above may be seen as familiar. It resembles the Template pattern, although not exactly equivalent, the idea here is still the same in a certain way, which is to transfer specific details about each order status to different classes.

“Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.”(Quote from the Gang of Four)

Even though in this example we are not dealing directly with an algorithm template. The principle of how this pattern works can be used here.

This is the idea behind the usage of an abstract base class or interface. We expose to the client just the details or methods that matter to it specifically. And the information that would lead to the choice inside the initial switch statement was deferred to the input.

1*cmc3AqijSLUSBUXmcEAyvA.png

Multiple orders diagram

Drawbacks of this approach

The most obvious drawback we can see is that such a decoupling comes at the cost of increasing the complexity of our code. We need a separate class for each different status/situation we want to deal with. Sometimes, when it leads to a much more complicated code at the end, or when there are a few conditions that will hardly ever change, it might be worth considering using a simple switch statement or if…else clauses.

This principle is just a guideline to make things easier!

Ultimately, the purpose of all these patterns and good practices is to facilitate your job as a developer, this is the whole point of applying them after all! They should be used with your critical thinking, so that you don’t dedicate your time and energy to something that will bring little to no benefits to your application.

Thank you for your attention, I hope this insight has been useful to you!

Bit: Feel the power of component-driven dev

Say hey to Bit. It’s the #1 tool for component-driven app development.

With Bit, you can create any part of your app as a “component” that’s composable and reusable. You and your team can share a toolbox of components to build more apps faster and consistently together.

  • Create and compose “app building blocks”: UI elements, full features, pages, applications, serverless, or micro-services. With any JS stack.
  • Easily share, and reuse components as a team.
  • Quickly update components across projects.
  • Make hard things simple: Monorepos, design systems & micro-frontends.

Try Bit open-source and free→

1*p3UFa6xnmmbrkTzfRm_EmQ.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK