Why you should isolate Express from the rest of your Node application
Tags: node, javascript, express
Published: 2018-12-03 23:50:22

---
title: Why you should isolate Express from the rest of your Node application
published: true
canonical_url: https://www.coreycleary.me/why-you-should-isolate-express-from-the-rest-of-your-node-application/
tags: node,javascript,express
---
<em><strong>Originally published at <a href="https://www.coreycleary.me/why-you-should-isolate-express-from-the-rest-of-your-node-application/">coreycleary.me</a></strong>. This is a cross-post from my content blog. I publish new content every week or two, and you can <a href="https://www.coreycleary.me/about/">sign up to my newsletter</a> if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets, links to great tutorials by other developers, and other freebies!</em>

You might have heard that you should "always layer your app" and "never let logic leak into other layers" before.

Those are statements made all over your favorite blogs, in "must read" programming books, and at tech meetups and conferences.

But you might have wondered <em>why</em> exactly it's a problem! So called "best practices" are often presented as such, but without an explanation of <strong>what</strong> will happen if you don't follow them and <strong>how</strong> they became best practices in the first place.

So let's look at <strong>one</strong> issue you'll run into with your Express REST API if you don't structure your app by layers. And then we'll look at an easy solution for avoiding this problem in the future (and fixing it if you have the issue).

<h3>`req` object, as far as the eye can see</h3>
Have you ever ended up with code that looks like this?
<img src="https://www.coreycleary.me/wp-content/uploads/2018/11/bad-way.png" alt="" width="1326" height="547" class="aligncenter size-full wp-image-836" />

The express `req` object is not only just in your controller, it's in your service layer too! And maybe - even worse - the `req` object is passed from the service layer into the database layer!

This is a violation of "always layer your app, and never let logic leak into other layers".

Now, for the reasons <strong>why</strong> it's a problem:

<h3>Marriage to Express</h3>
First, now the rest of the application depends not only on the `req` object, but on the Express framework as well. What happens if in the future you want to switch to Hapi or Koa? You would then have to find all the references to `req` and remove/replace them. And then you'd have to make sure the tests still work!

For small apps, this is probably not a lot of work to fix, but if it's a big app with lots of routes/controllers and lots of people working on it, it becomes a huge pain to change.

And what if you miss one of the `req` references and your tests don't catch it? Your users surely will...

<h3>Makes testing more cumbersome</h3>
It also makes testing more difficult. Now that `req` is being passed to our service function, in our tests we have to mock/reproduce that object.

That's fairly easy if you only have one or two properties from the object that you care about. But what if you have lots of things? What if you need to check a `req` header? Then it becomes difficult to manually reproduce.

Whereas if `req` was limited to your HTTP layer, you could use supertest or something similar to test your controller with an integration test, and you wouldn't need to mock `req` at all! And you would have more pure unit tests for your service layer functions.

<h3>Mixed concepts</h3>
Lastly, a big part of the reason we split apps into layers is because it decreases the "mental load" we have to deal with.

Building software is hard, and having to juggle multiple things in our brains becomes challenging. Sure, if you've got `req` past your HTTP layer into your service/business logic layer, it's just an object, and on the surface that might not seem too hard to reason about. <strong>But</strong> you've already got your business logic to reason about so why add something else? And isn't it now confusing that HTTP stuff is now mixed with your business logic?

<h3>Avoid / Fix</h3>
Now that we've gone over <strong>why</strong> it's a problem, let's discuss how to avoid/fix it.

In your `controller`:
```javascript
const { blogService } = require('../services')
const { createBlogpost } = blogService

const postBlogpost = async (req, res, next) => {
  const {user, content} = req.body
  try {
    await createBlogpost(user, content)
    res.sendStatus(201)
    next()
  } catch(e) {
    console.log(e.message)
    res.sendStatus(500) && next(error)
  }
}
```
The key line here is: `const {user, content} = req.body`

What we're doing is <strong>destructuring</strong> the `req` object - in this case the `body` property - to pull out only the data the `createBlogpost` service cares about. So now, Express is limited to our HTTP layer, and we don't have the request/HTTP logic leaking into the service layer.

If we want to swap out web frameworks in the future, it's much quicker and simpler to do so. The `req` object is limited to our controllers! And now we can test our other layers without mocking the request object.

<h3>Wrapping up</h3>
So remember - Express is the <strong>entry point</strong>, not the entire app. Its "context" should be limited to the HTTP layers and not leak into the business logic / service layers.

If you'd like to learn more about layering your REST API, <a href="https://www.coreycleary.me/project-structure-for-an-express-rest-api-when-there-is-no-standard-way/" rel="noopener" target="_blank">check out the best way I've found to structure/layer my apps.</a>

And if you found this post helpful, <a href="https://www.coreycleary.me/about/">here's that link again</a> to sign up to my newsletter to receive new content as soon as it's published. There's a lot to learn when it comes to Node (and JavaScript in general) - how the heck do you write tests, how do you structure your app, how do you handle async - and I'm writing new content to help make it easier. It doesn't have to be as hard as it sometimes is!