Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concerns about separating front-end and back-end with a NodeJS UI server [closed]

During the last months, we at work have been looking for a solution to the following problem: front-end developers can't easily modify the appearance of the website without the help of back-end devs.

Our culture as a team is mostly based on full-stack frameworks such as Symfony 2 and Ruby on Rails. We use templating engines but the templates are mostly written by backend-devs according to designers' markups.

The step we are considering to make is separating that monolithic architecture into a backend rest API and a NodeJS server as "UI server". The NodeJS server would handle the client request, consume the backend API and return a rendered template. By specifying clearly the API and the JSONs served, frontend and backend devs could then work in parallel with less problems. More info here: http://www.nczonline.net/blog/2013/10/07/node-js-and-the-new-web-front-end/

The thing is, we strongly believe that this separation is a good thing from an architecture POV, but we fear about the drawbacks. We suspect that it will make things way harder. None of us in the team has never worked with this kind of architectures, so any hint or experience about that would be very valuable.

Is it worth it? When? Why?

like image 207
carles Avatar asked May 26 '14 13:05

carles


1 Answers

What you need to do, is to have a clear line that separates your front-end from back-end. Then whatever the front-end needs from the backend-end team, it will documented comprehensively.

Let's say what you currently have is something like this:

app.get('/', function (req, res) {
    database.query('select * from user', function (err, result) {
        res.render(result);
    });
});

But then then you want to make it like this:

in UI server:

app.get('/', function (req, res) {
    request('apiServer/user', function (err, result) {
        res.render(result);
    });
});

in API server:

app.get('/user', function (req, res) {
    database.query('select * from user', function (err, result) {
        res.send(result);
    });
});

This is good. This will separate the front-end and back-end, but not only logically but also physically by being in different servers.

I believe if they are under the same server it will be just ok. Instead of above, just have them in different files:

in user.js:

exports.getAll = function (cb) {
    database.query('select * from user', cb);
};

in server.js:

var user = require('./user');
app.get('/', function (req, res) {
    user.getAll(function (err, result) {
        res.render(result);
    });
});

Why this is better than your solution? Because it separates touching database, and rendering the data, and also it doesn't have a extra http round trip.

Following a MVC pattern, you put files that are like user.js in a models directory, you put files like server.js in a controller directory. You make sure both are documented for front-end developers.

Now if your front-end developers are just gonna make UI changes, they will just touch the HTML files. If they want to add a section with data, they will read the backend documentation, they will add another call to the model to get the data they in the respective controller that renders the HTML.

Just make sure you will standardize everything, so when something new comes along, programmers in your team can somehow predict how the interface is going to be, use a good ORM to the heavy lifting on making database calls. If using an ORM is not your choice then make good abstractions.

So your application in layers can be like this:

Database --> ORM --> Models --> Controllers --> Views(HTML files)

Now the front-end developers, work on the right side the above diagram. They only need to know the documented API of their left side if it's nicely abstracted away, but they don't need to know how it works. Anyone who works on the controllers, only need to know the documented API of their left side which is Models. You can continue it all the way to the database on the left.

Then on each layer you can have unit tests and integration tests all the way to the front to make sure the interfaces are consistent.

And if you're team is large, with a large code base, make sure you always keep the backward compatibility in your interfaces, but with warnings in logs for deprecated stuff. Never try to break anything.

like image 175
Farid Nouri Neshat Avatar answered Sep 29 '22 00:09

Farid Nouri Neshat