Arquitectura de Software · Patrones arquitectónicos

El patrón MVC

Separar lo que sabe, lo que muestra y lo que decide.

Modelo

Vista

Controlador

Laboratorio: Notas del semestre · mvc-notas-lab.vercel.app

Dónde estamos

De funcionar a poder cambiar

Paso 1

El problema

El código funciona, pero cada cambio rompe algo más.

Paso 2

El principio

Separar responsabilidades: cada pieza, una razón para cambiar.

Hoy

El patrón

MVC: Modelo, Vista y Controlador.

Luego

La práctica

Laboratorio: del espagueti al MVC.

Una buena arquitectura no hace que el software funcione: hace que cambiarlo sea barato.

Arquitectura de Software · Patrón MVC

El punto de partida

El código espagueti

Una sola función: agregar()

Pantalla

n = document.getElementById('nombre').value

Regla + pantalla

if (total + p > 100) err.textContent = '…'

Datos

evals.push({ id: sig++, nombre: n })

Almacenamiento

localStorage.setItem('notas.v1', datos)

Pantalla

tabla.innerHTML = filas

Cuatro responsabilidades en un solo lugar

Cambiar una regla obliga a tocar la pantalla.

No se puede probar sin abrir el navegador.

Dos personas no trabajan a la vez sin pisarse.

La misma regla se copia en varios sitios.

Fragmentos de espagueti.html, el punto de partida del laboratorio

Una pregunta de mantenimiento

3

veces aparece escrita la nota mínima «3.0» en la versión espagueti.

En el HTML

(nota mínima 3.0)

En el cálculo

nec = (3.0 - acum) / …

En el estado

if (acum >= 3.0) …

¿Cuántas líneas tocas para pasarla a 3.5? Si olvidas una, la pantalla dice una cosa y el cálculo, otra.

Arquitectura de Software · Patrón MVC

Definición

Qué es un patrón arquitectónico

Una solución conocida y reutilizable a un problema de organización de todo un sistema.

Patrón de diseño

Escala: clases y objetos

Observer, Strategy, Factory Method.

Patrón arquitectónico

Escala: la estructura de la aplicación

MVC, capas, cliente-servidor.

MVC resuelve un problema concreto: separar la interfaz de la lógica del negocio.

Arquitectura de Software · Patrón MVC

Un poco de historia

De Xerox PARC a los frameworks

1979

Trygve Reenskaug lo formula en Xerox PARC, para el entorno Smalltalk.

1988

Krasner y Pope lo describen paso a paso para Smalltalk-80.

1994

El libro de la «Banda de los Cuatro» lo usa de ejemplo para Observer, Composite y Strategy.

2004 →

Llega a la web: Rails (2004), Django (2005), ASP.NET MVC (2009), Laravel (2011).

Cambiaron los lenguajes y las pantallas; la idea de separar tres responsabilidades sigue en pie.

Reenskaug (1979) · Krasner y Pope (1988) · Gamma et al. (1994)

La idea central

Tres piezas, tres responsabilidades

Modelo

Sabe

Los datos y las reglas del negocio.

No sabe

Que existe una pantalla.

Vista

Sabe

Cómo mostrar el estado y qué hizo el usuario.

No sabe

Ninguna regla de negocio.

Controlador

Sabe

Traducir lo que hace el usuario en órdenes.

No sabe

Dibujar ni calcular.

En Notas del semestre: el Modelo guarda pesos y notas y sabe si aprobó; la Vista dibuja la tabla y el resumen; el Controlador recibe «agregar», «calificar» o «eliminar».

Arquitectura de Software · Patrón MVC

El recorrido

Qué pasa cuando el usuario actúa

Paso 1

El usuario actúa

Escribe los datos y hace clic en «Agregar».

Paso 2 · Controlador

Traduce

Convierte el texto del formulario en una orden para el Modelo.

Paso 3 · Modelo

Decide

Valida las reglas, cambia su estado y avisa que cambió.

Paso 4 · Vista

Se redibuja

Lee el Modelo y muestra la fila nueva.

Si el Modelo rechaza la orden, lanza un error de reglas: el Controlador lo atrapa y le pide a la Vista que muestre el mensaje.

Arquitectura de Software · Patrón MVC

La regla de dependencias

Quién conoce a quién

Modelo

Vista

Controlador

ordena

ordena y registra eventos

lee

avisa, sin conocerla

Regla de oro: el Modelo no importa nada de la Vista ni del Controlador.

Arquitectura de Software · Patrón MVC · línea punteada: aviso por Observer, no una dependencia

Un patrón dentro del patrón

El Modelo avisa sin saber a quién

NotasModelo

suscribir(fn) {

  this.#suscriptores.add(fn);

  return () => this.#suscriptores.delete(fn);

}

 

#cambio() {

  this.#almacen.guardar(this.evaluaciones);

  for (const fn of this.#suscriptores) fn();

}

1 · Se suscriben

El Modelo guarda una lista de funciones.

2 · Algo cambia

Recorre la lista y las llama, una por una.

3 · No sabe quién escucha

Una tabla, un termómetro o una prueba.

Es el patrón de diseño Observer, que MVC usa por dentro.

Arquitectura de Software · Patrón MVC · extracto de la solución de referencia

En código

Notas del semestre en MVC

Modelo · modelo.js

agregar(datos) {

  if (!pesoValido(datos.peso))

    throw new ErrorDeReglas(

      'Peso fuera de rango');

  this.#lista.push(datos);

  this.#cambio(); // avisa

}

Vista · vista.js

render() {

  const r = modelo.resumen();

  acumulado.textContent =

    r.acumulado.toFixed(2);

  estado.textContent =

    TEXTO[r.estado];

}

Controlador · controlador.js

vista.alAgregar((datos) => {

  try {

    modelo.agregar(datos);

  } catch (e) {

    vista.mostrarError(

      e.message);

  }

});

Cada pieza cabe en una pantalla de código y tiene una sola razón para cambiar.

Extractos simplificados del laboratorio · Arquitectura de Software · Patrón MVC

Votación · 4 minutos

¿Modelo, Vista o Controlador?

  1. Calcular si el estudiante aprobó
  2. Poner en rojo el mensaje de error
  3. Decidir qué ocurre al hacer clic en «Eliminar»
  4. Validar que el peso esté entre 1 y 100
  5. Convertir el texto del formulario en un número
  6. Mostrar la nota con dos decimales
  7. Guardar los datos en localStorage
  8. Armar la tabla con textContent y createElement

Voten para cada una: M · V · C

Arquitectura de Software · Patrón MVC

Cuando MVC sale mal

Cuatro olores de un MVC mal hecho

Controlador gordo

Síntoma

Valida y calcula; el Modelo queda casi vacío.

Arreglo

Mover cada regla al Modelo.

Lógica en la Vista

Síntoma

Un if (nota >= 3) dentro del código de la pantalla.

Arreglo

La Vista le pregunta al Modelo; no decide.

Modelo que toca la pantalla

Síntoma

alert(), document o innerHTML dentro del Modelo.

Arreglo

El Modelo lanza errores; otros los muestran.

Modelo anémico

Síntoma

Solo datos y getters; las reglas viven en otro lado.

Arreglo

Que el Modelo proteja sus propias reglas.

En el laboratorio, las pruebas de arquitectura detectan los dos del medio.

Arquitectura de Software · Patrón MVC

La familia

MVC y sus parientes

MVC · hoyMVPMVVM
Quién mediaControladorPresentadorViewModel
La Vista…Lee el Modelo y se suscribeEs pasiva: el Presentador le da todoSe enlaza al ViewModel (binding)
Suele verse enFrameworks web de servidorEscritorio y móvilesInterfaces con enlace de datos

En la web, con servidor: petición → Controlador → Modelo → Vista (HTML).

Fowler lo resume así: bajo el nombre «MVC» conviven variantes muy distintas. Hoy fijamos una.

Arquitectura de Software · Patrón MVC · Fowler, «GUI Architectures»

En la práctica

MVC en los frameworks

ModeloVistaControlador
Laravel · PHPEloquent · app/ModelsBlade · resources/viewsapp/Http/Controllers
Spring MVC · JavaEntidades y servicios del dominioThymeleaf o JSPClases con @Controller
ASP.NET Core MVC · C#Carpeta Models/Views/ (Razor)Carpeta Controllers/
Django · Pythonmodels.pytemplates/views.py

Los nombres cambian; las tres responsabilidades siguen ahí.

Django lo llama MTV (Model · Template · View): lo que allí se llama «view» hace de controlador.

Arquitectura de Software · Patrón MVC · convenciones de carpetas de cada framework

La balanza

Beneficios y costos

Beneficios

  • Probar el Modelo sin pantalla
  • Varias vistas del mismo Modelo
  • Trabajo en paralelo: una pieza por persona
  • Cambios localizados

Costos

  • Más archivos y más indirección
  • Exagerado para una app de 100 líneas
  • Fácil mezclar roles: «¿esto dónde va?»
  • Hay que aprender el vocabulario

MVC no es un fin: es una forma de pagar menos cada vez que hay que cambiar.

Arquitectura de Software · Patrón MVC

Cómo saber si funcionó

¿Está bien separado? Tres preguntas

¿Pruebo el Modelo sin navegador?

npm test

39 pruebas del Modelo, sin abrir una sola página.

¿Agrego otra vista sin tocar el Modelo?

Parte 5B

El termómetro: un archivo nuevo y una línea en main.js.

¿Cambio dónde se guardan los datos?

Parte 5C

Solo almacen.js y main.js: el Modelo ni se entera.

Y una máquina lo vigila: pruebas de arquitectura que fallan si el Modelo usa el DOM o la Vista decide reglas.

Arquitectura de Software · Patrón MVC · npm run arquitectura

Manos a la obra · ≈ 2 h 20 min

El laboratorio de hoy

0 · Preparación10 min
1 · Leer el espagueti20 min
2 · El Modelo30 min
3 · La Vista20 min
4 · El Controlador20 min
5 · Tres cambios25 min
6 · Medir y entregar15 min

Cada equipo entrega

El enlace de su repositorio

npm test: 54 de 54 en verde

3 commits para los 3 cambios

ENTREGA.md completo

Ruta corta ≈ 100 min: partes 0 a 4

Guía: mvc-notas-lab.vercel.app/guia.html

Plantilla: github.com/xaviercardona-ops/mvc-notas-lab

Arquitectura de Software · Patrón MVC

Antes de empezar · 5 min

Demostración en vivo

1

npm start

Abrir espagueti.html y agregar una evaluación: funciona.

2

<b>hola</b> como nombre

La pantalla lo interpreta como HTML: un olor, y un riesgo.

3

npm test

Las pruebas del Modelo: rojo en el esqueleto, verde en la solución.

4

npm run arquitectura

Escribir document en el Modelo a propósito y ver cómo falla.

Arquitectura de Software · Patrón MVC

Cierre

Para llevarse

El Modelo no conoce a nadie

Lo que el Modelo no conoce, no se le rompe.

Un lugar por cada cambio

Cada razón para cambiar vive en una sola pieza.

MVC es un medio

Úsalo cuando la separación pague, no por moda.

Referencias

Reenskaug, T. (1979). Models–Views–Controllers. Informe técnico, Xerox PARC.

Krasner y Pope (1988). A cookbook for using the Model-View-Controller user interface paradigm in Smalltalk-80.

Gamma, Helm, Johnson y Vlissides (1994). Design Patterns. Addison-Wesley.

Buschmann et al. (1996). Pattern-Oriented Software Architecture, vol. 1. Wiley.

Fowler, M. GUI Architectures. martinfowler.com/eaaDev/uiArchs.html

Arquitectura de Software · Patrón MVC