MVC (Modelo, Vista, Controlador) es un patrón para organizar el código en una aplicación para mejorar la capacidad de mantenimiento.
Imagine un fotógrafo con su cámara en un estudio. Un cliente le pide que tome una foto de una caja.
Las arquitecturas no MVC tienden a estar estrechamente integradas entre sí. Si la caja, el controlador y la cámara fueran uno y el mismo objeto, tendríamos que separarnos y luego reconstruir tanto la caja como la cámara cada vez que quisiéramos obtener una nueva vista. Además, tomar la foto siempre sería como tratar de tomar una selfie, y eso no siempre es muy fácil.
bwaha escribió:
El autor se refiere a mvctree.py en wxPython como un ejemplo de diseño MVC. Sin embargo, todavía soy demasiado ecológico, así que encuentro ese ejemplo en particular demasiado complejo y no entiendo la separación que el autor recomienda.
MVC tiene que ver con la separación de las preocupaciones.
El Modelo es responsable de administrar los datos del programa (tanto los datos privados como los del cliente). La Vista / Controlador es responsable de proporcionar al mundo exterior los medios para interactuar con los datos del cliente del programa.
El modelo proporciona una interfaz interna (API) para permitir que otras partes del programa interactúen con él. La Vista / Controlador proporciona una interfaz externa (GUI / CLI / formulario web / IPC de alto nivel / etc.) para permitir que todo fuera del programa se comunique con él.
El Modelo es responsable de mantener la integridad de los datos del programa, porque si eso se corrompe, entonces se acaba el juego para todos. La Vista / Controlador es responsable de mantener la integridad de la IU, asegurándose de que todas las vistas de texto muestren valores actualizados, deshabilitando elementos del menú que no se aplican al foco actual, etc.
El modelo no contiene código de vista / controlador; no hay clases de widgets GUI, no hay código para diseñar cuadros de diálogo o recibir la entrada del usuario. La vista / controlador no contiene código de modelo; no hay código para validar URL o realizar consultas SQL, y tampoco hay un estado original: cualquier dato contenido por widgets es solo para fines de visualización, y simplemente es un reflejo de los datos verdaderos almacenados en el Modelo.
Ahora, aquí está la prueba de un verdadero diseño MVC: el programa debería ser esencialmente funcional incluso sin una Vista / Controlador conectado. De acuerdo, el mundo exterior tendrá problemas para interactuar con él de esa forma, pero siempre que uno conozca los encantamientos de la API del modelo apropiado, el programa mantendrá y manipulará los datos de manera normal.
¿Por qué es esto posible? Bueno, la respuesta simple es que todo es gracias al bajo acoplamiento entre las capas Modelo y Vista / Controlador. Sin embargo, esta no es la historia completa. Lo que es clave para todo el patrón MVC es la dirección en la que van esas conexiones: TODAS las instrucciones fluyen desde la Vista / Controlador al Modelo. El modelo NUNCA le dice a la Vista / Controlador qué hacer.
¿Por qué? Porque en MVC, mientras que la Vista / Controlador puede saber un poco sobre el Modelo (específicamente, la API del Modelo), pero el Modelo no puede saber nada sobre la Vista / Controlador.
¿Por qué? Porque MVC se trata de crear una clara separación de preocupaciones.
¿Por qué? Para ayudar a evitar que la complejidad del programa se salga de control y lo entierre a usted, el desarrollador, debajo de él. Cuanto más grande es el programa, mayor es el número de componentes en ese programa. Y cuantas más conexiones existan entre esos componentes, más difícil será para los desarrolladores mantener / ampliar / reemplazar componentes individuales, o incluso simplemente seguir cómo funciona todo el sistema. Pregúntese esto: al mirar un diagrama de la estructura del programa, ¿preferiría ver un árbol o la cuna de un gato? El patrón MVC evita esto último al no permitir conexiones circulares: B puede conectarse a A, pero A no puede conectarse a B. En este caso, A es el Modelo y B es la Vista / Controlador.
Por cierto, si eres agudo, notarás un problema con la restricción 'unidireccional' que acabamos de describir: ¿cómo puede el Modelo informar a la Vista / Controlador de los cambios en los datos de usuario del Modelo cuando ni siquiera se le permite sabe que la Vista / Controlador, no importa enviarle mensajes? Pero no se preocupe: hay una solución para esto, y es bastante ordenada, incluso si al principio parece un poco indirecta. Volveremos a eso en un momento.
En términos prácticos, entonces, un objeto de Vista / Controlador puede, a través de la API del Modelo, 1. decirle al Modelo que haga cosas (ejecutar comandos) y 2. decirle al Modelo que le dé cosas (devolver datos). La capa Vista / Controlador
envía instrucciones a la capa Modelo y extrae información de la capa Modelo.
Y ahí es donde su primer ejemplo de MyCoolListControl falla, porque la API para esa clase requiere que la información se inserte
en ella, por lo que vuelve a tener un acoplamiento bidireccional entre capas, violando las reglas de MVC y volviendo directamente a la arquitectura de la cuna del gato que [presumiblemente] intentabas evitar en primer lugar.
En cambio, la clase MyCoolListControl debe ir con el flujo, extrayendo los datos que necesita de la capa de abajo, cuando lo necesita. En el caso de un widget de lista, eso generalmente significa preguntar cuántos valores hay y luego preguntar por cada uno de esos elementos a su vez, porque esa es la forma más simple y flexible de hacerlo y, por lo tanto, mantiene el acoplamiento al mínimo. Y si el widget quiere, por ejemplo, presentar esos valores al usuario en un orden alfabético agradable, entonces esa es su perogativa; y su responsabilidad, por supuesto.
Ahora, un último enigma, como indiqué anteriormente: ¿cómo mantiene sincronizada la pantalla de la interfaz de usuario con el estado del modelo en un sistema basado en MVC?
Este es el problema: muchos objetos de Vista tienen estado, por ejemplo, una casilla de verificación puede estar marcada o no, un campo de texto puede contener texto editable. Sin embargo, MVC dicta que todos los datos del usuario se almacenen en la capa Modelo, por lo que cualquier dato que posean otras capas para fines de visualización (el estado de la casilla de verificación, el texto actual del campo de texto) debe ser una copia subsidiaria de los datos primarios del Modelo. Pero si el estado del Modelo cambia, la copia de la Vista de ese estado ya no será precisa y debe actualizarse.
¿Pero cómo? El patrón MVC evita que el Modelo introduzca una copia nueva de esa información en la capa Vista. Diablos, ni siquiera permite que el Modelo envíe un mensaje a la Vista para decir que su estado ha cambiado.
Bueno, casi. De acuerdo, la capa Modelo no puede hablar directamente con otras capas, ya que hacerlo requeriría que sepa algo sobre esas capas, y las reglas MVC lo impiden. Sin embargo, si un árbol cae en un bosque y no hay nadie cerca para escucharlo, ¿suena?
La respuesta, como puede ver, es configurar un sistema de notificaciones, proporcionando a la capa Modelo un lugar que pueda anunciar a nadie en particular que acaba de hacer algo interesante. Luego, otras capas pueden publicar oyentes con ese sistema de notificación para escuchar los anuncios que realmente les interesan. La capa Modelo no necesita saber nada sobre quién está escuchando (¡o incluso si alguien está escuchando en absoluto!); solo publica un anuncio y luego lo olvida. Y si alguien escucha ese anuncio y tiene ganas de hacer algo después, como pedirle al Modelo algunos datos nuevos para que pueda actualizar su visualización en pantalla, entonces genial. El modelo solo enumera las notificaciones que envía como parte de su definición de API; y lo que alguien más haga con ese conocimiento depende de ellos.
MVC se conserva y todos están felices. El marco de su aplicación puede proporcionar un sistema de notificaciones incorporado, o puede escribir el suyo si no (vea el 'patrón de observador').
...
De todos modos, espero que eso ayude. Una vez que comprenda las motivaciones detrás de MVC, las razones por las cuales las cosas se hacen de la manera en que son comienzan a tener sentido, incluso cuando, a primera vista, parecen más complejas de lo necesario.
Salud,
tiene