Atualizado: 02/01/2025

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.

Padrao MVC em Node.js

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, como localhost:3000/users/create, além de dois endereços gerais: a página principal e o endereço /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 no diretório da aplicação. Nesta pasta, criaremos um novo arquivo userController.js com o seguinte código:

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, chamado homeController.js, com o seguinte código:

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 são organizadas em um roteador separado, o homeRouter.

É importante notar que podemos adicionar o processamento de rotas usando diferentes métodos. No exemplo acima, usamos os métodos use e 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() na primeira linha também:

userRouter.get("/create", userController.addUser);

A única consideração é o tipo de requisição que será processada por essa rota. O método get() se limita apenas a requisições do tipo 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 no projeto. Em seguida, nesta pasta, criaremos um novo arquivo homeRouter.js com o seguinte código:

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. Também adicionaremos à pasta routes um novo arquivo userRouter.js, onde colocaremos o código para o segundo roteador:

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.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com