MVC: no es una buena arquitectura para la web

Febrero 17, 2008 at 11:06 am (Evangelios de Dioses de Silicio) ()

¿Alguna vez intentaron encontrar la tuerca correcta para un tornillo en particular en una caja llena de tuercas de diferentes tamaños y tipos? Bueno, así es como se siente el buscar la arquitectura de software apropiada. Algunas veces solo te dan unas pocas tuercas, e incluso si parecen del tamaño apropiado, terminas forzando el tornillo. Así es como se siente usar el patrón MVC para desarrollar sitios web.

¿Por qué es el MVC una mala elección para el desarrollo web? Veamos la historia del MVC.

MVC fue propuesto como una muy buena solución para el desarrollo en Smalltalk de interfaces gráficas en entornos de ventanas. Cada ventana estaba compuesta de una triada MVC. La vista se encargaba del dibujado de mapas de bits, el controlador atendía acciones del mouse y teclado, y el modelo guardaba el estado de la ventana y la información mostrada en ella. Cada vista esta asociada con un controlador y un modelo en su creación. Cualquier modelo podía ser asociado débilmente a cualquier vista, pero cada par controlador/vista siempre se mantenían asociados con su respectiva pareja. En realidad el controlador no se encargaba de manejar la lógica del negocio en la aplicación, su propósito era manejar la interacción del mouse y el teclado, y actualizar la vista acorde, lo cual no era una tarea trivial. El modelo podía ser compartido entre diferentes displays, por eso la necesidad de ser débilmente asociable, una necesidad que aún hoy persiste, pero no así para la asociación modelo/vista, ésta tenía un propósito diferente: el modelo debía poder notificar a las vistas asociadas sobre cambios que ocurrieran fuera de su entorno.

Además, las vistas estaban pensadas para ser incluidas una dentro de otra, o sea, de manera jerárquica (lo que significa que el MVC es por definición jerárquico, realmente no existe tal cosa como el MVC Jerárquico). Una vista de ventana tenía vistas hijo para los botones, campos de texto, menues, etc, y cada vista hija era además parte una tríada MVC.

Hasta acá todo bien. Hoy en día todas las tareas cubiertas por una arquitectura MVC son resueltas en las APIs para interfaces gráficas, y tenemos modelos diferentes para generar interacción con estas interfaces. El manejo de eventos es mayormente usado para agregar lógica que antes era agregada a un controlador concreto, que ahora fue reemplazado por un controlador genérico que envía eventos donde lógica foránea podría ser aplicada. La asociación de flujo de datos (dataflow binding) permite asociar orígenes de datos con el display donde mostrarlos, y se encarga de las dos direcciones del flujo de la información, de manera que el display pueda pedir los datos cuando se genera la vista, y recibir sucesivas actualizaciones cuando la información se modifica. Además, un modelo lazy se puede aplicar de manera que los datos se capturen solo cuando sean necesarios, en lugar de almacenarlos en memoria muy previamente a su uso.

En pocas palabras, MVC no es ya una preocupación del desarrollador de interfaces gráficas (a menos que trabaje en una API de interfaces gráficas).

Entonces, veamos que tan bien se puede exportar el MVC a un entorno diferente. Los sitios web (no hablemos del difuso concepto de “aplicaciones web”, el desarrollo web sigue siendo en su gran mayoría sitios web) son bastante diferentes que las interfaces gráficas de ventanas. Veamos cuales son las diferencias más importantes:

La web no es un entorno de ventanas. Sí, podes tener varias ventanas corriendo un navegador web, pero un sitio web desconoce todo sobre ventanas y no provee una interacción (a priori) entre páginas en diferentes ventanas. En otras palabras, no se supone que sepas que otra página web esta corriendo en otra ventana, o que puedas interactuar con ella. Actualmente es totalmente dejado al navegador el implementar tales cosas, y podrías usar javascript para hacerlo, pero no es para lo cual la web fue pensada, solo alguien pensando fuera de los parámetros habituales.

La web es pasiva. A pesar de que algunos sitios proveen la ilusión de ser activos, la web supuestamente es pasiva, o sea, pedís una página y no recibís sucesivas actualizaciones de la misma hasta que la pidas de nuevo. El desarrollo de sitios web consta mayormente en crear dinámicamente páginas a pedido. Nada ocurre si el usuario no pide una página web. Pero, de nuevo, esto sólo es la base común que comparte el desarrollo web, no significa que alguien pueda crear un sitio web que se actualice activamente y actúe como una aplicación de escritorio, pero sigue siendo solo alguien pensando fuera de los parámetros habituales. La web es solo un repositorio de hipertexto, hasta el día en que cambien los protocolos.

La navegación web carece de estado. Una interfaz de ventanas retiene el estado de sus vistas mientras las navegamos, la web no provee una navegación que retenga el estado. Podes acceder cualquier página web en cualquier momento, y no deberías esperar que, al volver a una página visitada previamente, ésta recuerde el estado en el que se encontraba cuando la visitaste antes. La persistencia y manejo del estado durante de la navegación es una de las mayores preocupaciones del desarrollo de sitios web, y sin importar que tan bien hechos sean los componentes que proveen esto, va a ser un work-around, y seguramente uno que no es aprueba de tontos. Tenemos las cookies para almacenar datos en el cliente, pero no son confiables y proveen capacidades muy limitadas. Además, la mayoría de los intentos de proveer una navegación con persistencia del estado rompen/romperían el mecanismo estándar de navegación que los navegadores proveen (atrás-adelante-historial).

La web está compuesta de muchos tipos de contenidos y en variadas codificaciones. En una web coexisten varios documentos de diferentes tipos, desde HTML, imágenes, hojas de estilo, XML, PDF, películas flash, applets Java, etc. Algunos pueden ser embebidos, algunos no. Algunos requieren ser codificados apropiadamente para ser mostrados adentro de otros, e incluso diferentes codificaciones son usadas dentro del mismo documento. Por ejemplo, adentro de un HTML, un texto plano tiene que ser codificado diferente si es parte del contenido o si está dentro de un atributo de un tag o una URL.

Entonces, ¿cómo estas diferencias hacen del MVC una mala elección para la arquitectura de un sitio web?

MVC fue diseñado para entornos de ventanas. Una página web no es una ventana ni funcional ni estéticamente. Un sistema de ventanas generalmente intenta evitar la sobrecarga de información por ventana, si hay más que mostrar es mejor hacerlo en una nueva ventana. Una página web no tiene otro opción que sobrecargarse de información, un usuario de la web no espera navegar demasiado para encontrar la información que espera. Nadie agregaría el logo, la cabecera, el menu de navegación, el pie de página, la información legal, etc, en cada ventana en un sistema de ventanas, pero en un sitio web… Además, las páginas web son más difíciles de descomponer jerarquicamente, donde los componentes básicos puedan ser manejados por tríadas MVC anidadas. O controlas todo lo que pasa en la página, o controlas todo lo que pasa en la página.

MVC puede manejar displays pasivos pero fue pensado para manejar displays activos. El par modelo/vista está mejor aplicado cuando maneja eventos que ocurren sin la interacción del usuario. Sin esto, se convierte en un pobre sistema de templates. MVC sería una buena opción para una API de interfaces gráficas AJAX hecha en el cliente en javascript, pero para el lado del servidor HTTP, mmmm…. no.

MVC asume que el modelo (estado de la vista) es persistente. Usualmente, las implementaciones MVC para la web proveen modelos para entidades en bases de datos de algún tipo, pero no hay un modelo concreto para la vista, particularmente, no hay almacenamiento del estado de la vista en el modelo. Por la manera en que la navegación ocurre en la web, no tiene sentido almacenar el estado de la vista, ya que sería reseteado con cada nuevo pedido. Podes almacenar algunos estados en la persistencia de la sesión, pero no es confiable (cookies). Además, dada la naturaleza de la web, tener un modelo correspondiente a la vista solo trasladaría la sobrecarga de información de la página al modelo.

MVC asume que la vista es persistente. O sea, la vista no se pierde mientras el controlador atiende a una acción. En la web la vista se pierde con cada acción del usuario: con cada pedido de una pagina web se descarta la pagina anterior y se la reemplaza por la nueva. Se puede argumentar que una aplicación AJAX pudiera circunvencionar esta situación, pero de todas maneras la aplicación AJAX estaría pidiendo datos al web server como si de páginas se trataran. Además, en una aplicación AJAX se pierden muchas de las funcionalidad esenciales de la web.

MVC fue diseñado para un ambiente gráfico común sin codificaciones especiales. Los tipos de contenidos que mostraba un sistema MVC eran solo bitmaps, la web maneja muchos mas tipos de contenidos. Además, no había codificaciones especiales que debían aplicarse según el contexto. El render de páginas web tiene una complejidad diferente que necesita ser manejado por, probablemente, más de un subsistema (la V de MVC sola no alcanza).

Conclusión: MVC no es la mejor opción para el desarrollo web ¿Qué puede usarse en su lugar que no sea el viejo rápido-y-sucio script php?

10 comentarios

  1. kNo dijo:

    “MVC fue diseñado para entornos de ventanas.” ¿Y qué? La idea subyacente es mucho mayor que un simple entorno de ventanas. La separación en las tres capas hace que el desarrollo web sea más simple sin tener que ver nada con las ventanas. ¿Problemas de mente cuadriculada?

    “MVC puede manejar displays pasivos pero fue pensado para manejar displays activos.” Este artículo está escrito en 2008 ¿verdad? Porque parece del 2000. Hoy día la web es completamente interactiva. El modelo MVC se ajusta perfectamente en este sentido y aunque no lo hiciese ¿cual sería el problema?

    “MVC asume que el modelo (estado de la vista) es persistente.” ¿De verdad has navegado alguna vez por internet? Verás, para escribir este blog has necesitado autentificarte. En la siguiente sesión, el servidor ya sabía que estas identificado, no lo has tenido que hacer otra vez. Se han guardado datos en el servidor y en el navegador que hacen la información persistente.

    “MVC fue diseñado para un ambiente gráfico común sin codificaciones especiales.” ¿De nuevo mente cuadriculada? ¿Si una cosa no estaba pensada en sus orígenes para algo no se puede usar? De nuevo decir que aunque la idea pudiese surgir en un entorno determinada, pensar que debe quedarse en él es ser muy estrecho de miras.

    Conclusión: No sabes lo que es la web. No sabes de qué hablas. No has programada nunca una aplicación y menos una aplicación web (si, si, aplicación web, que la web no es solo “un repositorio de hipertexto”).

  2. elhombregris dijo:

  3. Lucas dijo:

    Creo que MVC es la elección predilecta para el desarrollo web, es más creo que hay más desarrollo de aplicaciones web con el patrón MVC que aplicaciones de escritorio con la aplicación del mismo. Por algo existen tantos frameworks que asisten al desarrollo web con el patrón MVC.

    Saludos!

  4. elhombregris dijo:

    @Lucas

    No discuto que MVC sea una opción popular, discuto si su adopción busca realmente solucionar los problemas de la web, si se adapto correctamente desde su espacio de uso original.

    En última instancia también empece a preguntarme si es realmente MVC lo que proponen los frameworks desde RoR en adelante, ya que no son consistentes con el diseño original.

  5. Javier dijo:

    Hola,
    Bueno el análisis, pero no voy a coincidir, MVC esta orientado a “vistas” no ventanas, es mas general de lo que parece, aunque en su momento solo se asociaba a las vistas con las ventanas, ahora ya no es asi, y la arquitectura contempla esto. Sí creo q probablemente haya quedado un poco atrasado o desactualizado si pensamos en todas las posibilidades que hoy tenemos para el desarrollo de aplicaciones web (sobre todo incorporando AJAX), practicamente se pueden lograr aplicaciones casi de escritorio (ExtJS, JQueryUI, etc), y con todo esto, el modelo MVC se ve desbordado. Pero de todas maneras no veo una alternativa mejor y aun sigue siendo efectivo y ordenado, mas si usamos frameworks nuevos como por ejemplo cakephp 1.2 o similiares.

    Saludos.

  6. elhombregris dijo:

    @Javier

    nunca dije que MVC estuviera orientado a tal o cual cosa sino que su propósito original es manejar un entorno gráfico basado en ventanas. Si tuviera que sugerir cual es la orientación del MVC, diría que busca desacoplar la lógica de presentación del modelo de datos, y a su vez también desacoplar la lógica del manejo del input del usuario.

    El problema que planteo con esto es que en un sistema de ventanas se presupone que las ventanas retienen su estado cuando el usuario se dispone a ver otra cosa, y en la web esto no ocurre y tampoco es ni sencillo ni transparente implementar algo que lo simule.

  7. Pablo Aguiar dijo:

    Yo tengo el siguiente problema al utilizar mvc en web:
    La url se utiliza para dar las indiciaciones de que debe hacer el controlador: clase/modelo/variable1/variable2
    (en siempre utilizo url “amigables” para mvc)
    Por ejemplo:
    blog/ver/23 (para ver la novedad 23)
    Pero el problema surje por ejemplo cuando tengo que paginar:
    La paginacion debería ser enviada a una grilla de datos, (que tambien debería seguir el mvc) Pero la grilla de datos esta adentro de una vista por ejemplo….
    O sea: tendria que enviar instrucciones a 2 controladores, uno seria el de la clase blog, y otro el de la grilla que deseo paginar…
    La url “amigable” entonces se transforma en algo muy engorrroso…y la relación entre la url y el controlador se hace muy compleja….(no deseo usar AJAX para paginar el datagrid)

  8. Arturo dijo:

    Que tal Pablo Aguiar:

    Cuando utilizas grillas en la web, son completamente manejadas por la vista, esto no es incompatible con el patron MVC, porque una grilla no es persistencia de datos “per se” sino solo una parte de la vista, aun asi, la vista tambien se puede y se debe dividir a su vez en un patron MVC, el que sea engorroso o no, no significa que este mal, hay muchas herramientas que facilitan su implementacion.

    Saludos.

  9. elhombregris dijo:

    @Arturo

    Estas confundiendo la “grilla” constructiva en el diseño gráfico con la “grilla” como componente de interfaz (o patron de diseño de interfaces de usuario), o sea, Pablo se refiere a la forma en que se presentan los datos, una grilla como la de una planilla de calculo o una tabla de datos, vos te referís a una grilla como como la del framework css blueprint.

    Estas errando conceptos ahí, la “vista” es la parte de una triada MVC cuya responsabilidad es el “como” se muestran los datos desde una perspectiva de bajo nivel. En la web esto significa solo, y nada más, que tomar el modelo y generar el html apropiado. Eso es todo lo que la vista debe hacer y nada más que eso.

    Cuando el “como” se muestran los datos significa si uso una vista con una grilla, un listado, un arbol u otro componente, esto es una preocupación de alto nivel que no le concierne al MVC sino a la lógica de negocio u otro modulo que haya sido diseñado al propósito. O sea, no hay que olvidar que las triadas MVC están subordinadas a una lógica externa cuya responsabilidad es la de crear las vistas, responder a necesidades de los controladores, y proveer las entidades utilizadas en los modelos. O por lo menos esto es lo que debería hacerse en el MVC canónico.

    No es posible seguir descomponiendo una vista en triadas MVC porque no hay en una vista una división de responsabilidades que lo requiera. Tal vez lo que te confunde es que pueda suceder que una triada MVC que existe en el contexto de un servidor provea, en la salida de la vista, datos que son utilizados luego por una triada MVC que existe en el contexto del cliente, por ejemplo, al utilizar AJAX.

  10. elhombregris dijo:

    @Pablo Aguiar

    El problema del mapeo de urls es uno de los grandes dolores de cabeza a todos los que usamos en algun momento un framework MVC o cuasi-MVC. Ningún modelo usado genericamente llega resolver las necesidades reales de un sitio/servicio web. En general se estila usar /controlador/metodo-del-controlador/varibles-de-llamada… que es lo que vos usas pero con otros términos, y el problema de esto es que no es consistente ni con un modelo REST ni con un modelo SEF (search engine friendly).

    Tu problema puntual del paginado se debe a la cuestión de que en un entorno web no existe, a priori, persistencia de la vista. En el MVC canonico el controlador de la grilla es quien responde directamente a las acciones de navegación de página, cambiando el modelo sin necesitar pasar por las vistas superiores. En la web lo que sucede es que, una vez enviado el html al usuario, lo utilizado para generarlo se descarta. Al navegar a una nueva pagina el servidor vuelve a empezar de cero a generar el html sin recordar casi nada del estado en que estaba cuando le envio al usuario la otra pagina.

    La situación a resolver para que esto sea transparente presenta dos dificultades: 1) recrear la vista según el request, 2) distinguir donde se produjo la acción del usuario para forwardearla al controlador de la vista correspondiente.

    Una solución paleativa y simple a esto sería propagar el request por el arbol de vistas. Luego cada vista interpreta del request aquello que sabe va dirigido a sí, por ejemplo, la grilla va a identificar aquella porción de la url que indica la pagina pero la vista que la contiene la va ignorar y forwardear a la grilla. No es la mejor solución, pero es una solución.

Escribe un comentario