Refactoring Javascript code with Object Literals: A Clean and Readable Approach
Tags: javascript, refactoring, development
Published: 2023-07-04 18:26:31

This is and slightly modified article i wrote few years back on medium.
[link](https://medium.com/@razamoh/js-code-refactoring-how-to-refactor-conditional-statements-use-object-literals-instead-669c1933f089).


## Introduction:

When it comes to user authentication or multiple payment types, we often encounter complex conditional statements that can quickly become hard to follow. But fear not! There's a neat trick we can use to make our code more readable and maintainable: object literals. In this article, I'll explore how object literals can simplify user authentication or any related scenarios and make our code shine.

## The Initial Code:

Imagine you have a chunk of code that handles user authentication using different methods such as email, social login, and one-time passwords (OTP). Let's take a look at the initial code:

```javascript
const authenticateUser = (method, credentials) => {
    if (method === 'email') {
        this.authenticateWithEmail(credentials);
    } else if (method === 'social') {
        this.authenticateWithSocial(credentials);
    } else if (method === 'otp') {
        this.authenticateWithOTP(credentials);
    } else {
        throw new Error('Invalid authentication method.');
    }
};

const authenticateWithEmail = (credentials) => {
    // Here's where we authenticate using email credentials
};

const authenticateWithSocial = (credentials) => {
    // Here's where we authenticate using social credentials
};

const authenticateWithOTP = (credentials) => {
    // Here's where we authenticate using OTP credentials
};
```


## Refactoring with Object Literals:

To make our code cleaner and easier to read, we can leverage the power of object literals. Let's rewrite the code using this approach:

```javascript
const authenticationMethods = {
    email: this.authenticateWithEmail,
    social: this.authenticateWithSocial,
    otp: this.authenticateWithOTP
};

const authenticateUser = (method, credentials) => {
    const authenticate = authenticationMethods[method];

authenticate ? authenticate(credentials) : throw new Error('Invalid authentication method.');
};
```

## Let's Break it Down:
In our refactored code, we create an object literal called authenticationMethods. This handy object maps each authentication method to its corresponding authentication function. By doing this, we can easily access the appropriate authentication function based on the provided method.

Gone are the days of tangled if-else statements or lengthy switch cases. With object literals, our code becomes cleaner and more readable. If a new authentication method pops up in the future, all we need to do is update the authenticationMethods object without touching the authenticateUser function.

## Conclusion:

By utilising object literals, we can transform complex conditional statements into elegant and readable code. In this article, we've seen how this technique simplifies user authentication scenarios. Embracing this approach not only enhances the maintainability of our code but also makes it more understandable and enjoyable to work with.

I'd love to hear your thoughts and answer any questions you might have. So go ahead, give it a try, and let me know how object literals elevate your code to new heights!

## Alternate views
Suggested by @jonrandy 

The object literal is a bit of overkill here, since you effectively already have it on this. So, it can be made even simpler:

```javascript
const authenticateUser = (method, credentials) => {
  const methodName = `authenticateWith${method[0].toUpperCase() + method.slice(1)}`
  return (this[methodName] || ()=>{ throw new Error('Invalid authentication method.') })(credentials)
}
```
This way also scales to new authentication methods without having to change the code (providing you stick to the naming convention you provided) - making it more maintainable still.