Web MVC
Autor: Oliver Steele (artículo original acá) | ENGLISH
|
|
- 1. MVC de Escritorio
- 2. Programación de aplicaciones Web
- 3. MVC del lado del servidor
- 4. MVC del lado del servidor: detrás de las apariencias
- 5. Tiempo de ciclo
- 6. Densidad del cliente
- 7. Arquitectura RIA
- 8. Conclusión
La arquitectura Model-View-Controller (MVC - Modelo-Vista-Controlador) es una arquitectura estándar para aplicaciones interactivas. En una aplicación cliente-servidor, los componentes de MVC están distribuídos en al menos dos nodos de una red. Esto lleva a tener varias opciones respecto a dónde desplegar (deploy) cada componente de la arquitectura. Una solución tradicional es el modelo MVC basado en el servidor. La otra es el modelo Rich Internet Application (RIA). En una aplicación real con validaciones del lado del cliente, ambas opciones son más parecidas de lo que parecen.
MVC de Escritorio^
En una aplicación interactiva, típicamente hay un modelo de datos del dominio correspondiente, código para presentar dicho modelo al usuario, y código que actúa sobre el modelo en respuesta a la actividad que realiza el usuario. Por ejemplo, en un procesador de texto el modelo es el documento, que contiene entidades como párrafos, espacios y estilos. El sistema presenta el documento al usuario como (para que pueda ser visualizado) un conjunto de patrones de pixeles (es decir, texto con formato) e interpreta las pulsaciones de teclado y ratón como acciones de edición, formato y comandos de control.
Smalltalk-80 introdujo la arquitectura Model-View-Controller (MVC) para estructurar este tipo de aplicaciones. MVC separa el mantenimiento del modelo (el Modelo), la presentación del modelo (la Vista), y la interpretación de las entradas o acciones del usuario (el Controlador).
Flujo de control de Model-View-Controller2

Junto al usuario, los componentes de MVC forman dos ciclos de información y flujo de control:
- Ciclo de la Vista: Usuario → Controlador → Vista → Usuario. El usuario manipula un dispositivo de entrada - por ejemplo, con un click, mientras el cursor del ratón en la parte inferior de una barra de desplazamiento. El controlador responde enviando un mensaje a la Vista (por ejemplo, invocando a view1.scrollDown()). La Vista actualiza su estado (ajusta el valor de view1.xoffset), y actualiza la información que se presenta al usuario (invoca bitblt del área visible de view1, e invoca el método draw() de las vistas que intersecan el área involucrada).
- Ciclo del Modelo: Usuario → Controlador → Modelo → Vista → Usuario. El usuario manipula un dispositivo de entrada de una forma y en un contexto difente - por ejemplo, presiendo las teclas control+D mientras un ítem de una lista de contactos es seleccionado. El controlador actualiza el estado del Modelo, la vista se actualiza para reflejar el cambio en el modelo, y al usuario de le presenta la nueva vista. Por ejemplo, cuando el usuario la opción Eliminar de un menú, el código en el controlador va a invocaría a un método view.deleteRow(), el cual invoca a view.currentSelection.delete(), donde view.currentSelection es un objeto del Modelo y view.currentSelection().delete() es un método del Modelo. Dicho método cambia los datos del Modelo, los cuales notifican los objetos oyentes u observadores, por ejemplo invocando sus métodos registerChange(). El conjunto de oyentes incluye objetos de la Vista, que responden a la invocación actualizando su visualización.
En una aplicación de escritorio, el Modelo, la Vista, y el Controlador se ejecutan en la máquina con la cual el usuario interactúa. Este tipo de aplicación es simple de escribir (o mejor dicho, tan simple como el modelo lo permite); fácilmente toma ventaja de las características de la plataforma del cliente como ventanas de diálogo, almacenamiento local, y drag & drop. Las desventajas de un MVC de escritorio son las desventajas de las aplicaciones de escritorio en general: son difíciles de desplegar, tienden a ser dependientes de la plataforma, y generalmente se limitan a manejar datos en el sisteama de archivos local3.
Programación de aplicaciones web^
En una aplicación web, el software del lado del servidor (back-end) se ejecuta en un servidor, y el usuario interactúa con un navegador (browser)que se ejecuta en el cliente. El Modelo de datos se almacena en el servidor. Es definitiva, el usuario interactúa con software que se ejecuta en el cliente.
La programación Cliente-Servidor no es sencilla debido a que el sistema está distribuído a través de más de un nodo de una red. Parte del código tiene que ejecutarse en el cliente para interactuar con el usuario, mientras otra parte se ejecuta en el servidor para interactuar con el almacenamiento de datos.
En el caso de una aplicación web, el código que se ejecuta en el cliente incluye el navegador (browser). La naturaleza distribuída de una aplicación web crea dos desafíos. Uno es que la aplicación debe mostrar los datos que están en el servidor en un contexto ajeno en donde el cliente pueda visualizarlos correctamente. El otro es que la información sobre los eventos del usuario debe volver al servidor y reflejar los cambios.
La decisión arquitectónica acerca de un MVC Cliente-Servidor es qué nodos se despliega cada componente, y cómo manejar la comunicación entre ellos. ¿Deberían la Vista y el Controlador ejecutarse en el servidor o en el cliente? ¿Y el Modelo?

Existen varias formas de tomar estas decisiones. Una solución es un MVC del lado del servidor (Server-Side) -como se ve en la figura anterior-. Otra es una arquitectura RIA (Rich Internet Aplication -Aplicaciones Ricas de Internet). Pero todas las soluciones tienen cosas para comentar y analizar, debido a las siguientes reglas básicas:
- Al menos una parte del Modelo debe ejecutarse en el servidor. Esto se debe a que el Modelo es responsable de mantener la integridad de los objetos del negocio, y por ende ser inmune a clientes malintencionados. Además debe sincronizar los requerimientos paralelos de clientes si los cambios pasan a través de un cuello de botella en el código, aunque en un servidor con agrupamientos (clustered) esto no es tan trivial.
- El usuario debe tener la capacidd de visualizar la información presentada por la Vista. Esto implica que la Vista, no importa donde se ejecute, debe controlar la información que será vista por el cliente.
- El Controlador debe ser capaz de recibir eventos que representar la actividad del usuario.
MVC del lado del servidor^
En un MVC del lado del servidor, el Modelo, la Vista, y el Controlador se ejecutan del lado del servidor. La Vista genera una representación de la presentación. Esta representación es descargada al cliente, donde se visualiza. La interacción del usuario con el cliente es enviada nuevamente al servidor, donde generalmente resulta en una nueva presentación, que se descarga oportunamente y actualiza la presentación anterior. Esta operación es la actualización de la vista.
MVC del lado del servidor

En una aplicación web con un MVC del lado del servidor, la Vista genera una página HTML, la cual es enviado al cliente como una respuesta HTTP. El navegador, en el cliente, codifica los eventos del usuario como una URL con consultas y parámetros POST en un requerimiento HTTP. El controlador, en el servidor, interpreta esta información como cambios al Modelo o la Vista, y dirige el requerimiento a la Vista, la cual responde con otra página HTML. La actualización de la Vista en una aplicación web es implementada como un reemplazo o sustitución de la vista anterior por una nueva. En un navegador, esta acción es la actualización (refresco).
En la comunidad Java, “MVC” significa “Server-Side MVC (MVC del lado del servidor)”. En este contexto, MVC también se denomina Modelo 2. (Modelo 1 es una aplicación del lado del servidor sin esta arquitectura). JSP, Struts, y PHP son todas tecnologías que pueden ser utilizadas para implementar este tipo de MVC.
La ventaja de este MVC para el desarrollador es que si el Modelo se ejecuta en el servidor, esta arquitectura le permite usar el mismo lenguaje, librerías y estructuras de datos para implementar el resto de la aplicación, y además llamados locales para comunicarse entre componentes.
La desventaja es que la calidad de la experiencia del usuario es limitada por tres factores:
- Las actualizaciones de la Vista en este tipo de MVC tienen una mayor granularidad que en las aplicaciones de escritorio. Una aplicación MVC del lado del servidor generalmente no actualiza solamente una parte de la vista (o el nodo interior de una jerarquía); sino que crea una nueva vista y la sustituye por la anterior, incluso cuando la nueva vista sea casi idéntica a la anterior. La limitación de la experiencia del usuario en este caso es el refresco de la página completa.
- Los eventos del usuario en este tipo de MVC también tienen una mayor granularidad que en las aplicaciones de escritorio. Múltiples eventos del usuario desde el cliente, como clicks y comandos de teclado, son agregados a un requerimiento HTTP que resume su efecto. Esto tienen implicancia sobre el tipo de respuesta que el Controlador puede dar; por este motivo es practicamente imposible la manipulación directa como drag and drop (tomar y soltar) en esta arquitectura, y la validación del lado del cliente es difícil.
- Los dos puntos anteriores son casos especiales respecto del problema de que el ancho de banda en la comunicación entre el usuario y la aplicación es baja. La latencia de comunicación además es alta, comparada con la interactividad de una aplicación de escritorio - cualquier ciclo de Modelo o Vista que envuelva un refresco o actualización de página es costoso en ese sentido.
El MVC del lado del servidor es el camino más simple para el desarrollo de una aplicación que proporcione acceso a un Modelo existente. Permite el incremento de los gastos de recursos para desarrolladores a un limitado grado de interactividad del usuario. Para muchas aplicaciones, sólo se requiere interactividad limitada. Esto es especialmente cierto para los usuarios no consumidores de aplicaciones web: los usuarios y las organizaciones preferirían tener recursos para mejorar el modelo de negocio de la aplicación (back-end) y agregarle nuevas funciones, en lugar de utilizarlos para mejorar la experiencia del usuario.
MVC del lado del servidor: detrás de las aparencias^
Observemos nuevamente cómo interactúa el usuario con una aplicación MVC del lado del servidor. La Vista en esta aplicación no muestra directamente información en la pantalla del usuario; sino que crea información que le indicará al navegador del usuario que muestre dicha información. El cliente no lee de los dispositivos de entrada; el navegador lee estos dispositivos y resume las acciones en un requerimiento HTTP.
El diagrama anterior esconde esta complejidad confundiendo el Usuario y el Agente del Usuario (el navegador), y ubicando ambos dentro de la computadora (por eso wl usuario estaba dentro de la computadora en el MVC del lado del servidor). Pero el usuario humano no interactúa directamente con los protocolos HTTP y HTML. Entonces hay un componente de software adicional - el navegador - mediando la interacción del usuario con el componente servidor de la aplicación. El navegador tiene proopio Modelo, Vista y Controlador. Su Modelo es la página HTML. La Vista muestra la página en la pantalla, y el Controlador interpreta los eventos del teclado y ratón dependiendo de lo que el usuario haya seleccionado y de la posición de los elementos (como enlaces y elementos de formulario) en el navegador.
MVC del lado del servidor desacoplado (ligeramente)

Esto es una variante de una arquitectura MVC, en donde la Vista y el Controlador están separados en el cliente y el servidor. El mayor retraso o latencia de las transacciones HTTP (requerimientos y respuestas) ocurre entre los componentes: la Vista del servidor se comunica via HTML con la Vista del cliente, y el Controlador de la Vista se comunica via HTTP con el Controlador del servidor.

Tiempo de ciclo^
Hay una complicación adicional, ya que ahora hay dos ciclos de Vista. Las acciones del usuario que no requieren un refresco de página, como el desplazamiento (scrolling) o seleccionar un nuevo elemento de un formulario, inician in ciclo de la Vista en el cliente. Las acciones que requieren un refresco de página, como paginar y ver los siguientes diez ítems de una lista, o buscar productos que contienen la palabra "X", inician un ciclo de Vista en el servidor. Ninguna de estas acciones cambian el Modelo - ambas son ciclos de la Vista, no ciclos del Modelo - pero requieren diferentes tipos de cambios en la Vista.
Los ciclos que cruzan la frontera Cliente-Servidor - el ciclo del Modelo, y el ciclo de la Vista del servidor - son ciclos más costosos que los ciclos que abarcan un sólo nodo.
Densidad del cliente^
El paso final para terminar la figura anterior es tener en cuenta la validación, como verificar la sintaxis del número de una tarjeta de crédito o una dependencia entre entradas de un formulario (si seleccioné el item 1, entonces el cuadro de texto 2 no puede ser vacío). Teniendo en cuenta lo que un ciclo de la Vista involucra en el servidor, es deseable hacer todas las validaciones posibles del lado del cliente, para evitar el refresco de página. Como las entradas se validan con el modelo, se requiere descargar algo de lógica de la aplicación del servidor al cliente.
MVC del lado del servidor desagrupado
Podemos señalar esto como un caso especial de un MVC de Modelo-simple, del mismo modo en que antes lo hicimos cuando sólo la Vista y el Controlador se dividieron entre servidor y cliente. En esta interpretación el Modelo contiene múltiples componentes que se ejecutan en el servidor, y al menos una librería del lado del cliente que la Vista incluye en el HTML que se descarga al cliente.
Esto no es un cliente grueso (o gordo o espeso), o una Aplicación Rica de Internet (RIA). El único código corriendo en el cliente es el navegador, y lo que la página actual incluya. Esto es aún un MVC del lado del servidor, como lo producen JSP, Struts, CGI, u otras tecnologías del lado del servidor que generan HTML+JavaScript. Lo que cambia es que ahora el diagrama de la arquitectura ahora refleja la complejidad completa de la aplicación.
Esta complejidad incluye aplicaciones del mundo real que están aún siendo estudiadas a nivel académico: la programación de múltiples etapas de generación de código (Mac IE, Windows IE, Netscape, Mozilla, Safari, Opera), proceso de migración, y (normalmente manual) conversión CPS para mantener el estado del programa a través de las páginas. No es extraño que la programación web es complicada.
Arquitectura RIA^
Para comparar, la siguiente figura muestra la arquitectura RIA. En este caso incluye un modelo de negocio, para dar soporte a la interacción del cliente.

Conclusión ^
Cuando comencé a trabajar con RIAs, pensé que la comparación entre RIAs y aplicaciones cliente-servidor convencionales sería como ésta:
Server-Side MVC |
RIA |
![]() |
![]() |
Estos diagramas hacen la arquitectura RIA más compleja que las aplicaciones cliente-servidor. Pero en realidad lo que ocurre es que la complejidad real no está representada en el diagrama de la izquierda. Ese diagrama confunde el usuario y el cliente del usuario (navegador). No tiene en cuenta la interacción entre el usuario y el agente del usuario, sino que lo toma como un solo componente. Esto hace parecer la arquitectura más sencilla superficialmente, pero dicha arquitectura no tiene el suficiente nivel de detalle para representar el tipo de interacciones que determinan la experiencia percibida por el usuario, que incluye la interacción del usuario con el navegador.
Estos diagramas también simplifican la arquitectura de (algunos) RIAs, los cuales necesitan al menos algo del Modelo para poder soportar la funcionalidad RIA.
Una vez que las arquitecturas son desarrolladas, la comparación se parece más a esto:
| Server-Side MVC | RIA |
![]() |
![]() |
Esto hace parecer la arquitectura RIA más simple que un MVC del lado del servidor, porque sólo contiene una Vista.
Regresemos a la arquitectura espacial astronauta a la tierra. La arquitectura RIA puede parecer más sencilla sobre papel, pero todavía puede involucrar un despliegue más complicado. Es más sencillo sólo si hay una cantidad significativa de programación del lado del cliente.
Notas
1 Hay un punto intermedio entre cambiar el Modelo y cambiar la Vista, donde el usuario pre-visualiza un conjunto de cambios, en un cuadro de diálogo o un formulario web múltiple, antes de iniciar la acción en ellos mediante un botón Aceptar u Ordenar. Acá es donde el botón Deshacer o Atrás traen problemas. Sin embargo, la distinción es en general lo suficientemente clara como para organizar una arquitectura.
2 Este puede no ser tu MVC de cabecera. A veces el usuario es omitido en el diagrama. (El usuario se integra el flujo de control, pero después de todo no es parte de la arquitectura de software). Algunas veces el conector del Controlador a la Vista se omite. (Probablemente no se puede paginar o desplazarse con la barra en estas aplicaciones, o bien el estado de la presentación se considera parte del Modelo). Algunas veces hay más dependencia de control de flujo o conectores; y a veces hay componentes extra, representando el almacenamiento detrás del Modelo, o algunas cosas más. Pero ninguna de estas variaciones hacen una diferencia para lo que se discute en este artículo, que es lo que pasa cuando hay al menos un Modelo, un Controlador, una Vista, un cliente y un servidor.
3 Solamente porque el Modelo se ejecuta en la computadora de escritorio del usuario, no significa que el almacenamiento del Modelo es en el sistema de archivos de la máquina local. Ese es sólo el camino más accesible, y el uso típico de una aplicación de escritorio. Ubicando el almacenamiento en algún otro lugar es una ardua batalla para una aplicación de escritorio, pero viene "gratis" para una aplicación web. Por el contrario, el soporte a la interactividad (por ejemplo, respuesta sensible y manipulación directa) es una batalla cuesta arriba para un servidor de aplicaciones, y viene con facilidad en una aplicación de escritorio.









