materials

El patrón Modelo-Vista-Controlador

Modelo-vista-controlador (MVC) es el patrón de arquitectura de software más utilizado en la actualidad en desarrollo web (y también en muchas aplicaciones de escritorio). Este patrón propone separar la aplicación en tres componentes distintos: el modelo, la vista y el controlador:

Este patrón de arquitectura de software se basa en las ideas de reutilización de código y la separación de conceptos, características que buscan facilitar la tarea de desarrollo de aplicaciones y su posterior mantenimiento.

Una aplicación sin MVC

Si una aplicación no utiliza este modelo cuando una función modifica los datos debe además reflejar dicha modificación en la página para que la vea el usuario. Por ejemplo vamos a hacer una aplicación para gestionar un almacén. Entre otras muchas cosas tendrá una función (podemos llamarle addProduct) que se encargue de añadir un nuevo producto al almacén y dicha función deberá realizar:

// La función que se ejecuta cuando el usuario envía el
// formulario para añadir un producto debería hacer:

// Coge los datos del formlario
const name = document.getElementById('product-form-name').value
const price = document.getElementById('product-form-name').price
...
// Valida cada dato
if (!name || name.length < 5 || ...)
...
// Añade el producto a la BBDD
const prod = await addProductToDatabase(payload)
let newProd = new Product(prod.id, prod.name, prod.price, prod.units)
this.products.push(newProd)
...
// Pinta en la página el nuevo producto
const DOMproduct = document.createElement('tr')
...
document.getElementById('products-table').apendChild(DOMproduct)
// Gestiona los posibles errores producidos en todo este proceso
...

Como vemos, se va a convertir en una función muy grande y que se encarga de muchas cosas distintas por lo que va a ser difícil mantener ese código. Además toda la función es muy dependiente del HTML (en muchas partes se buscan elementos por su id).

Nuestro patrón MVC

En una aplicación muy sencilla podemos no seguir este modelo pero en cuanto la misma se complica un poco es imprescindible programar siguiendo buenas prácticas ya que si no lo hacemos nuestro código se volverá rápidamente muy difícil de mantener.

Hay muchas formas de implementar este modelo. Si estamos haciendo un proyecto con OOP podemos seguir el patrón MVC usando clases. Si sólo usamos programación estructurada será igual pero en vez de clases y métodos tendremos funciones.

Para organizar el código crearemos 3 subcarpetas dentro de la carpeta src:

De este forma, si quiero cambiar la forma en que se muestra algo voy directamente a la vista y modifico la función que se ocupa de ello.

La vista será una clase cuyas propiedades serán elementos de la página HTML a los que accedamos frecuentemente, para no tener que buscarlos cada vez y para que estén disponibles para el controlador. Contendrá métodos para renderizar los distintos elementos de la vista.

El controlador será una clase cuyas propedades serán el modelo y la vista, de forma que pueda acceder a ambos elementos. Tendrá métodos para las distintas acciones que pueda hacer el usuario (y que se ejecutarán como respuesta a dichas acciones, como veremos en el tema de eventos). Cada uno de esos métodos llamará a métodos del modelo (para obtener o cambiar la información necesaria) y posteriormente de la vista (para reflejar esos cambios en lo que ve el usuario).

El fichero principal de la aplicación instanciará un controlador y lo inicializará.

Por ejemplo, siguiendo con la aplicación para gestionar un almacén. El modelo constará de la clase Store que es nuestro almacén de productos (con métodos para añadir o eliminar productos, etc) y la clase Product que gestiona cada producto del almacén (con métodos para crear un nuevo producto, etc).

El fichero principal sería algo como:

const storeApp = new Controller()		// crea el controlador
storeApp.init()				// lo inicializa

// En desarrollo podemos añadir algunas líneas que luego quitaremos para
// imitar acciones del usuario y así ver el funcionamiento de la aplicación:
storeApp.addProductToStore({ name: 'Portátil Acer Travelmate E2100', price: 523.12 })
storeApp.changeProduct({ id: 1, price: 515.95 })
storeApp.deleteProduct(1)

Podéis obtener más información y ver un ejemplo más completo en https://www.natapuntes.es/patron-mvc-en-vanilla-javascript/