Padrão MVC - Node.js
O padrão MVC é um dos padrões mais comuns aplicados em aplicações web, incluindo aquelas desenvolvidas com Node.js.
O padrão MVC é composto por seguintes componentes:
Modelos: Definem a estrutura e a lógica dos dados utilizados.
Visualizações (Views): Definem a parte visual, ou seja, como os dados serão exibidos.
Controladores: Processam as requisições HTTP recebidas, utilizando modelos e visualizações para o processamento, e enviam uma resposta ao cliente, muitas vezes em forma de código HTML.
Sistema de roteamento: é um componente adicional, que define as rotas da aplicação, ou seja, o caminho que cada requisição deve seguir.
No geral, quando uma requisição chega à aplicação, o sistema de roteamento escolhe o controlador apropriado para processá-la. O controlador, ao processar a requisição, pode acessar dados através dos modelos e utilizar as visualizações para renderizar a resposta. O resultado desse processamento é enviado ao cliente, geralmente como uma página HTML que o usuário visualiza em seu navegador.

Vamos analisar brevemente como podemos aplicar o padrão MVC em aplicações Node.js.
Controladores
No padrão MVC, os controladores permitem a ligação entre as visualizações e os modelos, executando a lógica de processamento das requisições.
Como vamos usar o framework Express, primeiro adicionaremos seus pacotes ao projeto:
npm install express --save
No arquivo principal da aplicação, definimos o seguinte código:
const express = require("express");
const app = express();
// Definindo os roteadores
const userRouter = express.Router(); // Para endereços com "/users"
userRouter.use("/create", function (request, response) {
response.send("Adicionando usuário");
});
userRouter.use("/", function(request, response) {
response.send("Lista de usuários");
});
// Associando o roteador ao endpoint "/users"
app.use("/users", userRouter);
// Handlers gerais
app.get("/about", function (request, response) {
response.send("Sobre o site");
});
app.get("/", function (request, response) {
response.send("Página principal");
});
// Tratamento de erro 404
app.use(function (req, res, next) {
res.status(404).send("Não Encontrado");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Na aplicação, um roteador é definido e associado aos endereços que começam com /users
localhost:3000/users/create
/about
Neste exemplo, os handlers de rotas no roteador enviam uma única linha de resposta para simplificar. No entanto, a lógica de cada handler pode ser muito mais extensa, ocupando várias linhas de código. Além disso, podem existir muitas outras rotas e handlers correspondentes. Um terceiro ponto é que os handlers são agrupados: algumas rotas estão relacionadas a ações em torno de entidades específicas (como visualizar a lista de usuários ou adicionar usuários), enquanto outras representam funções gerais, como a página principal e informações sobre o site.
Criando Controladores
Agora, vamos modificar a aplicação, movendo toda a lógica de processamento para os controladores. Para isso, criaremos uma nova pasta chamada controllers
userController.js
exports.addUser = function (request, response) {
response.send("Adicionando usuário");
};
exports.getUsers = function(request, response) {
response.send("Lista de usuários");
};
Em seguida, adicionaremos um segundo arquivo na pasta controllers
homeController.js
exports.index = function (request, response) {
response.send("Página principal");
};
exports.about = function (request, response) {
response.send("Sobre o site");
};
Cada arquivo representa um controlador separado, que contém um conjunto de funções para processar rotas específicas.
Agora, usaremos esses controladores no arquivo principal da aplicação:
const express = require("express");
const app = express();
const userController = require("./controllers/userController.js");
const homeController = require("./controllers/homeController.js");
// Definindo os roteadores
const userRouter = express.Router();
const homeRouter = express.Router();
// Definindo as rotas e seus handlers dentro do roteador userRouter
userRouter.use("/create", userController.addUser);
userRouter.use("/", userController.getUsers);
app.use("/users", userRouter);
// Definindo as rotas e seus handlers dentro do roteador homeRouter
homeRouter.get("/about", homeController.about);
homeRouter.get("/", homeController.index);
app.use("/", homeRouter);
app.use(function (req, res, next) {
res.status(404).send("Não Encontrado");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Os controladores são incluídos como módulos padrão e, em seguida, suas funções são usadas para processar as rotas. Além disso, para simplificar a organização lógica, as rotas processadas pelo homeController
homeRouter
É importante notar que podemos adicionar o processamento de rotas usando diferentes métodos. No exemplo acima, usamos os métodos use
get
userRouter.use("/create", userController.addUser);
homeRouter.get("/about", homeController.about);
Neste caso, não há uma diferença fundamental: poderíamos usar o método get()
userRouter.get("/create", userController.addUser);
A única consideração é o tipo de requisição que será processada por essa rota. O método get()
Definindo Rotas
Vale ressaltar que dentro de cada roteador podem ser definidas várias rotas. Para facilitar a gestão das rotas, cada roteador pode ser organizado e incluído como um módulo separado. Para isso, criaremos uma nova pasta chamada routes
homeRouter.js
const express = require("express");
const homeController = require("../controllers/homeController.js");
const homeRouter = express.Router();
homeRouter.get("/about", homeController.about);
homeRouter.get("/", homeController.index);
module.exports = homeRouter;
Neste código, está definido todo o conteúdo relacionado ao roteador homeRouter
routes
userRouter.js
const express = require("express");
const userController = require("../controllers/userController.js");
const userRouter = express.Router();
userRouter.use("/create", userController.addUser);
userRouter.use("/", userController.getUsers);
module.exports = userRouter;
Após isso, o projeto completo ficará da seguinte maneira:
MVCAPP/ ├── controllers/ │ ├── homeController.js │ └── userController.js ├── routes/ │ ├── homeRouter.js │ └── userRouter.js ├── app.js ├── package.json └── node_modules/
Finalmente, vamos alterar o arquivo principal da aplicação:
const express = require("express");
const app = express();
const userRouter = require("./routes/userRouter.js");
const homeRouter = require("./routes/homeRouter.js");
app.use("/users", userRouter);
app.use("/", homeRouter);
app.use(function (req, res, next) {
res.status(404).send("Não Encontrado");
});
app.listen(3000, ()=>console.log("Servidor iniciado e aguardando conexões..."));
Dessa forma, ao mover a lógica de processamento de rotas e organizá-las em roteadores como módulos separados, o código da aplicação ficou mais simples e claro.