En una arquitectura MVC, ¿qué tan estrechamente unidos están el Modelo y la Vista al Controlador?


16

Tengo una aplicación que usa MVC, pero estoy luchando un poco sobre cómo se debe diseñar el controlador. Por ejemplo, la Vista solo está viendo un subconjunto de los datos del modelo a la vez. Sin embargo, no estoy seguro de cómo exactamente se debe organizar. ¿Es normal que la Vista o el Modelo invoquen directamente funciones en el Controlador, por ejemplo? ¿A través de algún tipo de interfaz? ¿O están totalmente encapsulados y nunca saben sobre el controlador o entre ellos?

Solo como una edición; Esta es una aplicación personalizada que no está escrita en ningún marco web, por lo que no estoy buscando detalles específicos del marco aquí y tengo la libertad de hacer mi propia elección.


1
No responderé porque mi experiencia es limitada en arquitecturas MVC, pero por todo lo que he escuchado y hablado con otros, los M&V están estrechamente unidos entre sí, pero no el C. El M generalmente llama a funciones en el C y el V a menudo solo se une a algún subconjunto de la M.
Steven Evers

8
@SnOrfus: Eso es exactamente lo opuesto a lo que pensaba: los M&V están acoplados a la C pero no entre sí.
DeadMG

1
¿Cómo pueden tantas respuestas estar tan equivocadas? Aquí lea la versión de MS msdn.microsoft.com/en-us/library/ff649643.aspx
Reactgular

Respuestas:


15

El controlador controla el flujo de actividad. El usuario realiza esta acción, el controlador pasa los datos de la vista al dominio que hace lo que sea necesario y luego, en función de las respuestas, el controlador le dice al marco qué vista mostrar a continuación (y le da suficientes datos para hacer entonces).

Por lo tanto, el controlador debe estar acoplado al modelo de dominio, hasta cierto punto. es decir. Podría poner una capa de servicio en el medio pero, por definición estricta, se convierte en parte del dominio.

También está acoplado a los datos de la vista, pero no a la vista en sí. es decir. simplemente dice "mostrar la vista del cliente utilizando estos detalles del cliente". El marco luego decide dónde debe encontrar esa vista.

Ahora esto debería permitirle desacoplar el modelo de dominio de la vista, utilizando un modelo de vista de los mismos datos. Algunos desarrolladores hacen esto, otros no, y creo que es en gran medida una cuestión de preferencia personal.

En Rails, se le recomienda que empuje los objetos de dominio (ActiveRecord) a la vista y confíe en que la vista no aprovecha ese acceso (por ejemplo, no debe llamar a customer.save desde la vista, aunque estaría disponible).

En el mundo .NET, tendemos a reducir el riesgo al no permitir cosas que no deberían suceder y, posiblemente por esa razón, me parece que el modelo de vista separada es más popular.


1
Ver modelo es una práctica muy común cuando se trata de pruebas unitarias. Normalmente mapearía automáticamente el modelo de dominio o un objeto DTO a un modelo de vista. Luego usaría su modelo de vista en una vista. Ver modelo es fácilmente comprobable y no está vinculado a una capa de abajo.
CodeART

7

Nota: Robert C. Martin (también conocido como tío Bob) explica esto de una manera mucho mejor y humorística en su discurso principal, Architecture the Lost Years . Un poco largo pero enseña muchos buenos conceptos.

tl; dr: No pienses y planifiques tu aplicación en términos de MVC. El marco MVC es solo un detalle de implementación.

Lo más confuso de MVC es que los desarrolladores intentan usar todos los componentes pegados.

Intente pensar en los términos de un programa, no en los términos del marco.

Tu programa tiene un propósito. Toma algunos datos, hace cosas con datos y devuelve algunos datos.

De esa manera, controlleres el mecanismo de entrega de su programa.

  1. Un usuario envía una solicitud a su programa (por ejemplo, agregue un producto al carrito de compras).
  2. El controlador toma esa solicitud (información del producto e información del usuario), llama a la parte necesaria de su programa que manejará esta solicitud $user->addToCart($product)
  3. Su programa ( addToCartfunción del userobjeto en este caso) hace el trabajo que está destinado a hacer y devuelve una respuesta (digamos success)
  4. El controlador prepara la respuesta utilizando lo relevante view: por ejemplo. en el objeto controlador$this->render($cartView('success')

De esta manera, los controladores se desacoplan del programa y se utilizan como mecanismo de entrega. No saben cómo funciona su programa, solo saben qué parte del programa debe llamarse para las solicitudes.

Si desea utilizar otro marco, su aplicación no necesitará un cambio, solo tendrá que escribir controladores relevantes para llamar a su programa para solicitarlo.

O si desea hacer una versión de escritorio, su aplicación seguirá siendo la misma, solo tendrá que preparar un mecanismo de entrega.

Y el Model. Piense en ello como un mecanismo de persistencia.

En la forma OO, hay objetos en su programa que contienen los datos.

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

Cuando agrega un producto al carrito de compras, puede agregar el product::idal user::shoppingCart.

Y cuando desee conservar los datos, puede usar la modelparte del marco, que generalmente consiste en usar un ORM, para asignar las clases a las tablas de la base de datos.

Si desea cambiar el ORM que usa, su programa permanecerá igual, solo cambiará la información de mapeo. O si desea evitar las bases de datos, puede escribir los datos en archivos de texto sin formato y su aplicación seguirá siendo la misma.


Entonces, escribe tu programa primero. Si está programando con la forma 'OO', use objetos simples del lenguaje. No pienses en términos de MVC al principio.


Gran video. Gracias. Sin embargo, no estaría de acuerdo con tu interpretación. MVC no es un detalle en el significado que el tío Bob tiene allí. Notarás que MVC es un patrón arquitectónico muy parecido a su patrón "Interactor / Entidad / Límite" que está estableciendo. Por otro lado, cualquier sistema MVC en particular, como Spring o lo que sea, es algo que recomienda aplazar. Sin embargo, como explica, estos marcos que se denominan "MVC" es una especie de bastarización del término.
Edward Strange

Sí, escribí eso en la forma en que la gente piensa qué MVCes. Por eso escribí MVC Framework.
Hakan Deryal

2

Martin Fowler hace un buen trabajo al describir el paradigma MVC. Aquí hay un enlace a su artículo sobre él http://martinfowler.com/eaaDev/uiArchs.html

Tenga en cuenta su cita sobre la presentación separada "La idea detrás de la presentación separada es hacer una división clara entre los objetos de dominio que modelan nuestra percepción del mundo real y los objetos de presentación que son los elementos de la GUI que vemos en la pantalla".


1

Aquí hay un ejemplo simple de cómo MVC se puede usar en una aplicación Java Swing típica ...

Digamos que tiene un Panel que contiene un Botón y un Campo de Texto. Cuando se presiona el botón, se dispara un evento, lo que lleva a algún cambio de estado en la aplicación. Una vez que se registra el cambio de estado, TextField se deshabilita.

Este, entonces, sería el enfoque típico adoptado por una simple aplicación MVC ...

El controlador se registra como el oyente de los eventos de la vista. Cuando se hace clic en el Botón, la Vista en sí no maneja el evento; el controlador lo hace. El controlador es específico de Swing ya que debe tratar con eventos relacionados con Swing.

El Controlador recibe esta notificación y debe decidir quién debe manejarla (La Vista o el Modelo). Dado que este evento cambiará el estado de la aplicación, decide enviar la información al Modelo, quien es responsable de los datos y la lógica del programa. Algunos cometen el error de colocar la lógica del programa en el controlador, pero en OOP, los modelos representan datos y comportamiento. Lea a Martin Fowler sobre su versión de esto.

El modelo recibe el mensaje en el contexto adecuado. Es decir, no tiene ninguna referencia a Swing ni a ninguna otra referencia específica de GUI. Este mensaje le habla al Modelo y SOLO al modelo. Si se encuentra importando declaraciones javax.swing en el Modelo, no está codificando el Modelo correctamente.

Luego, el Modelo establece su estado en 'deshabilitado' y procede a notificar a las partes interesadas sobre este cambio de modelo. The View, al estar interesado en este evento, ya se ha registrado como Observador de cualquier cambio de modelo. Una vez que la Vista recoge el evento de cambio de estado del Modelo, procede a deshabilitar su TextField. También es legal que la Vista obtenga información de solo lectura directamente de su Modelo sin tener que pasar por el Controlador (generalmente a través de una interfaz específica expuesta por el Modelo para dicha actividad)

Al promover un acoplamiento tan suelto entre la presentación y la lógica empresarial y las capas de datos, encontrará que su código es mucho más fácil de mantener. A medida que los sistemas crecen, también lo hará su enfoque de MVC. Por ejemplo, Hierarchical MVC es una extensión que se usa a menudo para vincular triadas MVC para formar grandes sistemas de toda la empresa sin acoplar subsistemas


0

El acoplamiento (el tipo que desea evitar) implica una dependencia mutua entre dos clases. Es decir, un Foo depende de un Bar y un Bar depende de un Foo, por lo que realmente no puede modificar uno sin modificar el otro. Eso es algo malo

Sin embargo, no puedes evitar tener ALGUNAS dependencias. Las clases tienen que saber un poco el uno del otro, de lo contrario nunca se comunicarían.

En el patrón MVC, el controlador controla la comunicación entre el modelo de dominio y la vista de presentación. Como tal, el Controlador debe saber lo suficiente sobre el Modelo para pedirle que haga lo que se supone que debe hacer. El Controlador también debe saber lo suficiente sobre la Vista para poder presentarla al cliente o usuarios. Entonces, el controlador del modelo tiene dependencias en ambos. Sin embargo, la Vista puede existir perfectamente bien sin el Controlador: no hay dependencia allí. Del mismo modo, el modelo no depende del controlador, simplemente es lo que es. Finalmente, el Modelo y la Vista están completamente separados el uno del otro.

Esencialmente, el controlador es el nivel de indirección que desacopla la vista del modelo, para que no tengan que conocerse entre sí.


Ah, por eso los votos negativos escribí mal. Quise decir que el controlador tiene dependencias de ambos. D'oh!
Matthew Flynn

-5

En mi experiencia, en general, el modelo solo depende de una vista, no específica, a menudo como observador ... si tiene algún tipo de acoplamiento.

La vista generalmente se acopla a lo que sea que esté mirando, lo que tiene sentido. Es difícil encontrar una vista que se pueda desacoplar de lo que está viendo ... pero a veces puedes tener un acoplamiento parcial o algo así.

El controlador a menudo tiende a acoplarse a ambos. Esto también tiene sentido, ya que su trabajo es convertir los eventos de vista en cambios de modelo.

Por supuesto, esta es solo una tendencia que he observado y realmente no dice nada sobre ningún ejemplo específico.

Para comprender qué es MVC y cuál es la relación de acoplamiento, debe analizar cómo surgió MVC. El entorno en el que se creó MVC era uno en el que no existían los "widgets" como elementos de formulario con los que puede crear diálogos. Una "vista" era una caja y dibujaba cosas. Una vista de texto sería un cuadro que dibujaría texto. Una vista de lista era un cuadro que dibujaría una lista. El "controlador" recibió todos los eventos de mouse y teclado del sistema UI que tuvieron lugar en esa vista; no hubo eventos "textChanged" o "selectionChanged". El controlador tomaría todos estos eventos de bajo nivel y generaría interacción con el modelo. El modelo, al ser modificado, notificaría sus puntos de vista; desde entonces hemos llegado a ver esta relación como "observador" y '

ESA es la esencia del patrón MVC. Dado que este tipo de programación de IU de bajo nivel generalmente ya no se realiza, el MVC ha evolucionado en muchas direcciones diferentes. Algunas cosas que llevan ese nombre hoy en día casi no tienen nada que ver con el MVC y realmente deberían llamarse de otra manera. Sin embargo, todavía se puede usar en el sentido de un diálogo como un todo que interactúa con un objeto más grande. Sin embargo, hay muchas mejores alternativas.

Básicamente, todo lo que el MVC estaba destinado a resolver sucede ahora dentro de los widgets y es algo que ya no tenemos que usar.


Para aquellos que piensan que saben mejor:

http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod

http://msdn.microsoft.com/en-us/library/ff649643.aspx

Estoy seguro de que hay más, pero esos son solo los primeros de la lista en google. Como puede ver, el modelo depende en gran medida de una interfaz de vista en MUCHAS implementaciones. Generalmente un modelo es observable y la vista es un observador.

Pero, ¿por qué dejar que los hechos se interpongan en el camino ...

Un artículo ya publicado en otra respuesta también respalda mis declaraciones:

http://martinfowler.com/eaaDev/uiArchs.html

Si la gente quiere seguir diciendo que TODOS en la industria del diseño están equivocados, entonces está bien.


44
Esto es claramente incorrecto. ¡Un modelo no debe depender nunca de una vista! Incluso si esa vista es abstracta o una interfaz. ¡Un modelo debe estar completamente desacoplado de la presentación!
Falcon

3
La respuesta es incorrecta. El modelo no depende de una vista o controlador.
CodeART

2
@Crazy Eddie Usted dijo: "En mi experiencia, en general, el modelo solo depende de una vista, no específica, a menudo como observador" Su referencia citada dice: "Sin embargo, el modelo no depende de la vista ni del controlador". ¿Has leído el artículo citado? No lo parece
CodeART

2
@Crazy Eddie: No me importa lo que escriba alguien en un proyecto de código horrible. Este es un diseño horrible. Usar un observador para escuchar los cambios está bien, pero poner una interfaz de presentación en un modelo de dominio está muy mal. El código citado del artículo es defectuoso en algunos aspectos fundamentales con respecto a MVC. Incluso permite que el modelo dependa implícitamente del controlador. Que porqueria.
Falcon

3
@Crazy Eddie: jajaja @ downvote alboroto. ¿Te enfurecí?
Falcon

-7
  • El controlador envía el modelo a una vista y procesa el modelo enviado desde las vistas, sin embargo, no está estrechamente acoplado a una vista o modelo.

Si el controlador estaba estrechamente acoplado a una vista, entonces estaremos en un mundo de formularios web. Tendría un código detrás del cual estaría vinculado a un archivo de plantilla (aplicable a los formularios web ASP.NET)

Debido a esto, el controlador no está acoplado a un modelo o una vista. Es solo un mecanismo para procesar solicitudes y enviar respuestas.

  • La vista está estrechamente acoplada a un modelo. Realice cambios en su modelo (por ejemplo, cambie su propiedad) y tendrá que realizar cambios en su vista.

  • El modelo no está bien acoplado a una vista. Realice cambios en una vista y esto no afectará a un modelo.

  • El modelo no sabe nada sobre el controlador o las vistas donde se puede usar. Por lo tanto, el modelo no está estrechamente acoplado a una vista o controlador.

Otra forma de pensar sobre esto:

  • Realizar cambios en un controlador: la vista y el modelo no se verán afectados

  • Realizar cambios en un modelo: la vista se interrumpirá ya que depende de un modelo

  • Realizar cambios en una vista: el modelo y el controlador no se verán afectados

Este acoplamiento suelto en los proyectos MVC es lo que los hace fáciles de probar.


1
Esto está tan mal que no es gracioso. Ni siquiera vale la pena explicarlo. Simplemente ignora esta respuesta por completo.
Reactgular

1
@MathewFoscarini Deja de llorar y deja una "respuesta correcta"
CodeART

2
jajaja, toda la teoría del diseño detrás de MVC es que no dependen el uno del otro.
Reactgular

Te he dejado más información, espero que tenga sentido
CodeART
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.