Saltar al contenido

Comprender el patrón MVC en Nodejs – Comunidad DEV

Esta es la segunda parte del desarrollo basado en pruebas con Nodejs, Express, Mongoose & Jest, en la primera parte, configuramos nuestro entorno de desarrollo y ejecutamos nuestra primera prueba. En este tutorial, nos centraremos en crear los puntos finales utilizando la arquitectura MVC.

Definición de términos

MVC – Controlador de vista de modelo

Model View Controller es un patrón de arquitectura de software que implica la separación de la lógica de la aplicación en tres elementos interconectados: Modelo, Vista y Controlador.

API relajante

REST es un acrónimo de Representation State Transfer, API por otro lado es un acrónimo de Application Program Interface. Una API RESTful es un estilo arquitectónico para una interfaz de programa de aplicación (API) que usa solicitudes HTTP para acceder y usar datos.

Supuse que está familiarizado con los términos involucrados en este tutorial. Empecemos.

En el tutorial anterior, teníamos una estructura de carpetas muy básica, con pocas dependencias. Instalemos las dependencias necesarias para nuestro desarrollo de API.

$ npm i --save-dev body-parser dotenv nodemon

Después de la instalación, su archivo package.json debería verse como el siguiente.

{
  "name": "tdd-with-nodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest",
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "body-parser": "^1.19.0",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jest": "^26.6.3",
    "mongoose": "^5.11.9",
    "nodemon": "^2.0.6"
  }
}

Notará que hemos configurado nuestro script de inicialización para que se ejecute con nodemon, nodemon realizará un seguimiento de cada cambio realizado en nuestro archivo index.js y actualizará nuestra aplicación en consecuencia. A continuación, configuremos un servidor. cree un nuevo archivo dentro del directorio raíz de su aplicación llamado ** index.js ** y pegue el código a continuación.

require('dotenv').config();
const mongoose =  require("mongoose");
//const articles = require("./routes/article.routes");
const bodyParser =  require("body-parser");

const app = exepress();
const port = 8000;

mongoose.connect(process.env.mongoURI, {useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true })
.then(res => console.log(`Connection Succesful ${res}`))
.catch(err => console.log(`Error in DB connection ${err}`));

//body-parser config;
app.use(exepress.json());
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());

app.get("/", (req, res) => {
    res.send(`<h1>Hello!</h1>`)
});

app.listen(port, () => {
    console.log(`Application is listening at port ${port}`);
});

//register the enpoints
//app.use("/api/v1/articles", articles);

No olvide crear un .env file y agregue su URI de la base de datos así: mongoURI = mongodb + srv: // tu-db-uri. A continuación, inicie la aplicación escribiendo el siguiente comando en su terminal.

Debería obtener una respuesta en su terminal que dice: La aplicación está escuchando en el puerto 8000 Y Conexión exitosa [object Object]. Si abres http: // localhost: 8000 deberías conseguir “¡Hola!” registrado en su pantalla también.

Este tutorial pretende enseñarle cómo estructurar correctamente su Nodjs aplicación para encajar en el patrón MVC, por lo que estaríamos separando nuestra lógica empresarial de nuestro controlador y archivos de rutas. Aprenderemos más sobre esto en el tutorial de Estructura en capas, que es el tutorial final de esta serie.

Construyendo el modelo (Article.js)

A continuación, creemos nuestro modelo. Cree una nueva carpeta dentro del directorio raíz del proyecto, navegue hasta la carpeta y cree un nuevo archivo llamado Article.jsy copie y pegue el código a continuación para crear el modelo para nuestra API.

const mongoose = require("mongoose");
const Schema = mongoose.Schema;


const articleSchema = Schema({

    title:{
        type: String,
        required: true,
    },

    body:{
        type: String,
        required: true,
    },

    article_image: {
        type: String,
        required: false,
    },

    date:{
        type: Date,
        default: Date.now(),
    }

});


module.exports = Article = mongoose.model("Article", articleSchema);

Nuestro modelo es muy básico, tiene un título, cuerpo, y fecha objeto. Puede aprender más sobre la construcción MongoDB Esquemas que usan Mongoose leyendo el documento oficial aquí.

Creación del servicio de artículos (ArticleService.js)

Para construir el ArticleService.js necesita crear una carpeta llamada servicios para albergar nuestro ArticleService.js expediente. Copie y pegue el código siguiente en su ArticleService.js.

const Article = require("../models/Article");

module.exports = class ArticleService{
    static async getAllArticles(){
        try {
            const allArticles = await  Article.find();
            return allArticles;
        } catch (error) {
            console.log(`Could not fetch articles ${error}`)
        }
    }

    static async createArticle(data){
        try {

            const newArticle = {
                title: data.title,
                body: data.body,
                article_image: data.article_image
            }
           const response = await new Article(newArticle).save();
           return response;
        } catch (error) {
            console.log(error);
        } 

    }
    static async getArticlebyId(articleId){
        try {
            const singleArticleResponse =  await Article.findById({_id: articleId});
            return singleArticleResponse;
        } catch (error) {
            console.log(`Article not found. ${error}`)
        }
    }

    static async updateArticle(title, body, articleImage){
            try {
                const updateResponse =  await Article.updateOne(
                    {title, body, articleImage}, 
                    {$set: {date: new Date.now()}});

                    return updateResponse;
            } catch (error) {
                console.log(`Could not update Article ${error}` );

        }
    }

    static async deleteArticle(articleId){
        try {
            const deletedResponse = await Article.findOneAndDelete(articleId);
            return deletedResponse;
        } catch (error) {
            console.log(`Could  ot delete article ${error}`);
        }

    }
}

Construyendo el controlador (article.controller.js)

A continuación, comencemos a escribir nuestros puntos finales de API, cree una nueva carpeta dentro de su directorio raíz llamado controladores, navegue hasta la carpeta y cree un nuevo archivo llamado article.controller.js. copie y pegue el código a continuación.

const ArticleService = require("../services/ArticleService");

module.exports = class Article{

   static async apiGetAllArticles(req, res, next){
       try {
         const articles = await ArticleService.getAllArticles();
         if(!articles){
            res.status(404).json("There are no article published yet!")
         }
         res.json(articles);
       } catch (error) {
          res.status(500).json({error: error})
       }

   }

   static async apiGetArticleById(req, res, next){
      try {
         let id = req.params.id || {};
         const article = await ArticleService.getArticlebyId(id);
         res.json(article);
      } catch (error) {
         res.status(500).json({error: error})
      }
   }

   static async apiCreateArticle(req, res, next){
      try {
         const createdArticle =  await ArticleService.createArticle(req.body);
         res.json(createdArticle);
      } catch (error) {
         res.status(500).json({error: error});
      }
   }

   static async apiUpdateArticle(req, res, next){
      try {
         const comment = {}
         comment.title        = req.body.title;
         comment.body         = req.body.body;
         comment.articleImage = req.body.article_image

         const updatedArticle = await ArticleService.updateArticle(comment);

         if(updatedArticle.modifiedCount === 0){
            throw new Error("Unable to update article, error occord");
         }

         res.json(updatedArticle);

      } catch (error) {
         res.status(500).json({error: error});
      }
   }

   static async apiDeleteArticle(req, res, next){
         try {
            const articleId = req.params.id;
            const deleteResponse =  await ArticleService.deleteArticle(articleId)
            res.json(deleteResponse);
         } catch (error) {
            res.status(500).json({error: error})
         }
   }

}

Construyendo las rutas (article.routes.js)

Para comunicarnos con nuestros puntos finales, necesitamos configurar nuestras rutas con las solicitudes correspondientes. Crea una nueva carpeta llamada rutas, dentro de la carpeta, cree un nuevo archivo llamado article.routes.js. Puede elegir nombrar la carpeta como desee, pero siempre es bueno mantener nombres de archivos y directorios significativos.

const  express =  require("express");
const router = express.Router();
const ArticleCtrl = require("../controllers/article.controller");


router.get("/", ArticleCtrl.apiGetAllArticles);
router.post("/", ArticleCtrl.apiCreateArticle);
router.get("/article/:id", ArticleCtrl.apiGetArticleById);
router.put("/article/:id", ArticleCtrl.apiUpdateArticle);
router.delete("/article/:id", ArticleCtrl.apiDeleteArticle);

module.exports =  router;

Si ha seguido el tutorial hasta este punto, la estructura de su carpeta debería verse como el fragmento de abajo.

├── tdd-with-nodejs
 ├── controllers
     ├── article.controller.js
 ├── models
     ├── Article.js
 ├── routes
     ├── article.routes.js
 ├── services
     ├── articleService.js
├── test

Poniendolo todo junto

Cuando trabaje con el patrón MVC, asegúrese siempre de mantener la técnica de Separación de preocupaciones (SoC). La separación de preocupaciones (SoC) es un principio de diseño para separar las aplicaciones de software en distintas secciones, de modo que cada sección aborde una preocupación separada. Una preocupación es un conjunto de información que afecta el código de una aplicación de software. Profundizaremos en este tema en el próximo tutorial, que es el último de esta serie.

Antes de concluir, probemos uno de los puntos finales. Enviar una CORREO solicitud al / api / v1 / articles endpoint utilizando una herramienta de prueba API de su elección. En mi caso, Cartero Debería obtener el objeto de respuesta como respuesta para su artículo recién creado similar al fragmento a continuación.

Eso es todo por este tutorial. felicitaciones por llegar hasta ahora en esta serie. Nos vemos en el próximo tutorial.

Este contenido se publicó originalmente aquí.