DEV Community

Cover image for Why should you separate Controllers from Services in Node REST API's?

Why should you separate Controllers from Services in Node REST API's?

Corey Cleary on February 21, 2019

Originally published at coreycleary.me. This is a cross-post from my content blog. I publish new content every week or two, and you can sign up to ...
Collapse
 
anduser96 profile image
Andrei Gatej

I just started a project in which I use Express and my app structure also implies the use of controllers and services.

However, I decided to approach this app structure in an OO way.

class Controller {
    constructor (name) {
        const Service = require('../services');
        this.service = new Service(name);
    }

    insertOne (req, res) {
        const paramsBody = req.params.body;

        this.service.insertOne(paramsBody);

        res.json({
            message: 'success'
        })
    }
}

Here’s the Service class.


class Service {
    constructor (name) {
        const dbName = require('../db')[`${name}DB`];
        this.db = new dbName();
    }

    inserOne (params) {
        // business logic here 
        return this.db.insertOne(params);
    }
}

My question is: do you think using OOP in this case is redundant? I mean, this could be achieved with plain js objects.
If you were to work on a project with a structure like this, would you feel comfortable working on further?

Thank you for your time!

Collapse
 
ccleary00 profile image
Corey Cleary

Hey, great question Andrei - I personally tend to favor using plain objects and functions over using classes. In general, I try to follow the mantra of "don't use a class where a function will work just as well". I've seen the bad things that can happen when classes get inherited too much and creates complex understanding of what 'this' refers to, having to trace back up the class hierarchy, etc.

That being said, I think there are two things to consider: 1) if you're working on a team that is more familiar with the class-based approach, then it's probably worth using that approach (although it's definitely worth discussing with your team if classes are really needed are not). 2) sometimes Services need setup in the constructor and/or to maintain state. That is a more valid use case for a class (although you could look into using a factory function instead if you have some complex setup).

Either way - classes/OOP vs just functions - the structure/code organization is what I think is most important. And not putting business logic in the controllers.

Collapse
 
anduser96 profile image
Andrei Gatej

Thank you for your answer!

Initially I was going for plain objects, but then I realized that I would repeat the same functions for almost each service(same goes for controllers).

So I thought I would use a single blueprint service class and in the constructor I would choose the right db class using a factory pattern(that’s at least how I see things, it seems to be working well).

Anyway, I make sure that business logic goes into services, and the controller is the ‘orchestrator’.

Best of luck!

Collapse
 
mazyvan profile image
Iván Sánchez

Have you guys ever tried nest.js? It is a really really cool node.js framework that solved many of the architectural design problems on node applications. It's very SOLID friendly and uses all of this great kind of stuff (Controllers, Services, Entities, DTOs, Repositories, and many more) also it uses typescript by default and is build on top of express.js

I'm thinking of write a post about it. So follow me to check it out later.

Collapse
 
anduser96 profile image
Andrei Gatej

Sounds awesome! Can’t wait for the post!

Collapse
 
lschultebraucks profile image
Lasse Schultebraucks

This of course does not only apply to Node Rest API, this applies to every backend Rest Service, no matter of the technology used.

Also mapping and the separation of DTOs and Enties is very important.

Collapse
 
janguianof profile image
Jaime Anguiano

very useful : ) please more posts like this!

Collapse
 
ccleary00 profile image
Corey Cleary • Edited

Glad to hear it, and you got it

Collapse
 
klanmiko profile image
Kaelan Mikowicz

I like the idea of refactoring controllers into smaller services. Though, how does the concept of a service differ from a regular async function?

Collapse
 
ccleary00 profile image
Corey Cleary • Edited

Services are just an organizational concept - and they don't have to be async functions, they can be any function (or collection of functions).