Express - Suggested experience, how to handle this type of code repetition

Asked

Viewed 60 times

3

I’m studying the library (Express) and the language (Javascript), but this type of repetition below ends up bothering me and. I wonder what you would do in the situation to reduce the repetition of code.

This is a middleware I’m making for a route and, if you notice, there’s a section where I check the username, password, email, fullName and birthDate, that return exactly the same thing, but with the name of the model changed. I ended up spending 5 lines to do this.

The question is: Is there any way to reduce this repetition of code?

module.exports = {
register: async (req, res) => {
        const { 
            username,
            password,
            email,
            fullName,
            birthDate
         } = req.body

         if (!username) return res.json({error: 'Username not found.'})
         if (!password) return res.json({error: 'Password not found.'})
         if (!email) return res.json({error: 'Email not found.'})
         if (!fullName) return res.json({error: 'Full name not found.'})
         if (!birthDate) return res.json({error: 'Birthdate not found.'})

         const userEmailExists = await userService.fetch( { email } ) ? true : false
         const userNameExists = await userService.fetch( { username } ) ? true : false

         if (userEmailExists) return res.json({error: 'User email already exists.'})
         if (userNameExists) return res.json({error: 'Username already exists.'})

         const user = await userService.create({ username, password, email, fullName, birthDate })

         user.password = undefined

         return res.status(200).json(user)
         
    }
}

2 answers

3


First, regarding the repetition of "validation", you can do something like suggested in the other answer:

['username', 'password', 'email', 'fullName', 'birthDate'].forEach((key) => {
  if (!req.body[key]) return res.json({ error: `${key} not found.` });
});

However, this approach, although extremely valid, is somewhat limited, since you send an error message with the exact key of the object, which may be a bit out of character with the original message. Comparing the error message to be received by fullName empty, we have:

  • To fullName empty in the original code:
    Full name not found.
    
  • To fullName empty in the above code, which uses the key itself in the error message:
    fullName not found.
    

You can work around this difference from the message using an array of objects, but is it really worth it?

In addition, it is noticed that you have fields that require a more accurate validation, such as email and birthDate. This way, it may be worth searching for validation libraries that already give you this ready. Commonly used examples are yup or joi (search on NPM).

However, if the only thing you want to do is check the presence of the properties in the object, the suggested code is fully valid.


Another point of important mention that can be improved is this:

const userEmailExists = await userService.fetch( { email } ) ? true : false
const userNameExists = await userService.fetch( { username } ) ? true : false

There is no need to use a ternary operator there. It is not even necessary to explicitly convert to boolean type (with double negation !! or builder Boolean), since the if does this for you. Therefore, only the following is enough:

if (await userService.fetch({ email }))
  return res.json({ error: 'User email already exists.' });

if (await userService.fetch({ username }))
  return res.json({ error: 'Username already exists.' });

Finally, I suggest using a semicolon at the end of each statement. It may sound "fresh" and I know that Javascript "accepts" the semicolon and "works" code, but it avoids some bizarre situations that can occur if you don’t use them, like this and this (see more about this here).

A real example that could happen. Depending on where you put the following code (which has been suggested):

['username', 'password', 'email', 'fullName', 'birthDate'].forEach((key) => {
  if (!req.body[key]) return res.json({error: `${key} not found.`});
});

No semicolon in the rest of the code (or at the beginning of the array opening - ;[), you would probably see the problem. Demonstrate below.

console.log(1)

[1, 2, 3].forEach((num) => {
  console.log(num)
})

  • 1

    Luiz, what sensational tips! This certainly covers my difficulty, thank you! Do you know any Patterns design material in functional programming? !

  • Nothing that has been commented here has much to do with functional programming, but an excellent reference to learn more about how Javascript works is this excellent book: "Javascript for inpatient programmers". If you want to learn functional programming (in fact), I suggest going to a more paradigm-oriented language, like Haskell. Then you go back to JS and apply the concepts you learned.

2

[username,password,email,fullName,birthDate].forEach(key => {
  if (!req.body[key]) { return res.json({error: `${key} not found`}) }
});
  • 1

    Beware that since the AP code does not use semicolons, depending on where it is placed, this code can cause an error. It is not exactly the same thing, but the answers of this question give an idea of why. Also, you should not have used the items from array as strings?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.