DEV Community

Cover image for [Clean Code] Guards: You shall not pass!
César O. Araújo
César O. Araújo

Posted on

[Clean Code] Guards: You shall not pass!

Hi everyone!! let me ask you something: have you ever felt the pain when looking at a code like this one below?

 if (email && email.includes('@')) {
   if(password && password.trim() !== '') {
     // DO SOMETHING
   }
 }
Enter fullscreen mode Exit fullscreen mode

This is just an example, but imagine a 4-7 nested if statements.

It is indeed common to beginners create pieces of code like that and even healthy because, in my opinion, a programmer must feel the pain of writing a dirty code to catch the value of Clean Code.

Nested if statements can really be a pain in the ass if they get too big but we can clean this up using something called Guards

Guards?

This is a really simple concept to understand: They basically verify if there is something wrong, i.e validations, and then you stop the execution of your function.

function usingGuards(email, password) {
 if(!email || !email.includes('@')) {
   console.log('Email is not valid');

   return; // that's where the magic happens
 }

 if(password && password.trim() !== '') {
   // DO SOMETHING
 }

}
Enter fullscreen mode Exit fullscreen mode

As you can see on the code above, the first if condition is now our Guard. It will stop the execution if an invalid email is passed. Really simply, right?

The code is still dirty because of its abstraction levels but I'm not going to talk about it on this article. Just focus on the Guards for now.

It's a simple way of avoiding really nested if statements. You also can have more than one Guard, check this out:

function usingGuards(email, password) {
 if(!email || !email.includes('@')) {
   console.log('Email is not valid');

   return; // that's where the magic happens
 }

 if(!password && !password.trim() === '') {
   console.log('Password is not valid');

   return;
 }

 // DO SOMETHING
}
Enter fullscreen mode Exit fullscreen mode

Now that we are using our Guards in the right way, we are free to write any code related to the business logic because in the end, we're doing the validation with our Guards.

One last quick tip: The need of usage of Guards can be easily identified if you have a if-else statement where the else is the negative output:

 if (user) {
   // DO SOMETHING
 } else {
  console.log('that's an error!');
 }
Enter fullscreen mode Exit fullscreen mode

Try to do this on your own and see your code readability increase!

NOTE: I'm doing this with JavaScript but you can do it with any other language, the principles are the same.

Do you have opinions or something to add? don't be afraid, leave a comment!

Thanks for reading! =)

Top comments (2)

Collapse
 
fernandobasso profile image
Fernando Basso • Edited
Yeah, it is nice to combine guards with early
returns to avoid nesting logic inside ifs.

Your explanation is very good! I would like to add
two more very simple snippets of code that help one
to visualize how guards with early returns help
avoid unnecessary NESTING. The snippets bellow don't
bring anything new beyond what was already shown in
the post. They just show and emphasize some points
under a different perspective.

┌────
│ function f(x) {
│   if (x > 0) {
│     // Logic NESTED inside if.
│   }
│ }
└────

We can do this:

┌────
│ function f(x) {
│   if (x < 0) return 'Oops...';
│
│   //
│   // Main logic NOT nested inside if.
│   //
│ }
└────

By using this second approach, we reduce the need to
write logic too deeply nested inside of ifs (or any
other control structures for that matter). Less
nesting is generally better :)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
oaraujocesar profile image
César O. Araújo

That's great, Fernando! it is definitely a rich approach. I often use this one writing nodejs. =)