En MVC, ¿debería un modelo contener modelos de subvista?

8

Algunos antecedentes:

Un colega y yo tenemos diferentes interpretaciones de MVC, lo que significa que, dado el mismo problema, estamos encontrando soluciones radicalmente diferentes. Él viene de un fondo de Java donde cada componente de MVC puede modelar tradicionalmente un objeto y yo vengo de un fondo de Haskell y tengo poca o ninguna experiencia con OOP.

El espacio del problema:

El problema que estamos tratando de modelar actúa un poco como un entorno de escritorio. Tenemos una noción de la sesión de los usuarios (tal vez su inicio de sesión, su fondo de escritorio) y los procesos en su escritorio (por ejemplo, iTunes, Finder, etc.) que tienen sus propias propiedades de modelo (minimizadas, etc.).

Estamos de acuerdo con el siguiente punto: creemos que HMVC es la mejor representación. Estamos de acuerdo en que tenemos dos objetos MVC, Session(escritorio) y Process(aplicación) y que no queremos Processque tenga una noción Sessiono un vínculo de retroceso.

Sin embargo, una vez que estamos en desacuerdo es el significado central de MVC y cómo eso afecta dónde guardamos la lista de procesos en el escritorio de los usuarios .

Su interpretación:

Argumenta un punto muy válido que tradicionalmente es fácil de modelar en código y en nuestro sistema de renderizado. Él dice que la lista de procesos debería ser una lista de ProcessControllerobjetos dentro de los SessionControllercuales a su vez tienen sus modelos como objetos separados dentro de ellos. Esto significa que hay una cantidad significativa de estado dentro de ambos SessionControllery SessionModelque es relevante para lo que SessionViewnecesita renderizar.

Esto parece estar muy en armonía con lo que pudimos leer en Internet en una breve búsqueda.

Mi interpretación:

Mi interpretación requiere el mayor cambio arquitectónico y parece más difícil de implementar en el código, pero creo que es más conceptualmente correcto. Quisiera que alguien explique por qué este no es el caso, o presente un modelo diferente (si no MVC) que se alinee con esta interpretación y resalte algunas fortalezas y debilidades para ambos patrones para que podamos tomar la decisión más informada (ninguno de nosotros tiene Una sólida formación en arquitectura de software).

Veo MVC como una tríada con tres componentes intercambiables: el Model, el Controllery el View. Esto concuerda con lo que puedo leer en Internet, y algunas fuentes dirán cosas como "las vistas, los controladores y los modelos con la misma interfaz deberían ser intercambiables con diferentes efectos". La forma en que imagino que esto funciona es la siguiente:

  • Cuando intercambia el modelo, está cambiando la forma en que se validan o almacenan los datos
  • Cuando intercambia el controlador, está cambiando el comportamiento de la página , pero no nada que pueda alterar el contenido de los datos conceptuales de la página.
  • Cuando intercambias la vista, estás cambiando la forma en que se muestra la página

A partir de esto, razoné que dado cualquiera Modely View, intercambiar solo el controlador no debería cambiar los datos que la página presenta inicialmente porque el controlador debería cambiar solo el comportamiento y no el 'contenido' de la página. Creo que esto se alinea con la visualización conceptual del controlador como un 'controlador de estación' en un sistema ferroviario, un plan de la vía ferroviaria como modelo y la manifestación física real y la apariencia / sensación de las pistas (en diferentes sabores, digamos ' Real 'o' Virtual 3D ') como la vista.

Aquí es donde no estamos de acuerdo:

Argumento que debido a que SessionViewlos diferentes procesos en el escritorio cambian los datos que se mostrarán al usuario en el escritorio (modelo los procesos como datos relevantes ), el SessionModeldebe contener la lista de instancias de ProcessModel. Esto significa que el uso de cualquier aleatorio SessionControllercon el mismo SessionViewdebería mostrar conceptualmente los mismos datos (procesos en el escritorio).

Argumenta que tiene más sentido para un Modelnunca saber acerca de otro modelo. Esto significa que SessionControllertendría una lista de ProcessControllers dentro y cada Controllerobjeto tiene un enlace a su modelo. Dado un SessionViewy el mismo SessionModelpero diferente, SessionControllerlos datos que se muestran al usuario deben ser radicalmente diferentes.

Discuta a favor / en contra de cada interpretación y ayúdenos a alcanzar el resultado más informado.

¡Gracias por tu tiempo!

kvanberendonck
fuente
1
Cambiar el controlador puede hacer que el método del controlador represente una vista diferente o devuelva un objeto diferente. Por lo tanto, su argumento probablemente solo tenga sentido si el controlador que está intercambiando se ajusta a una interfaz / contrato específico. Por lo tanto, no hay garantía de que el nuevo controlador muestre los mismos datos a la vista; el controlador solo está obligado a procesar o devolver lo que está programado para procesar o devolver.
Robert Harvey
Entonces, ¿el punto de entrada al render debería ser el controlador y no la vista (con el controlador como argumento)?
kvanberendonck
1
Usted, proveniente de Haskell, debe relacionarse con lo siguiente: Creo que MVC es solo un modelo abstracto de relaciones entre partes de un programa, pero qué partes deben desempeñar la vista de rol, modelo o controlador depende del problema que enfrenta. . Del mismo modo, la teoría de categorías es solo un conjunto de reglas para ayudar a formalizar las relaciones entre los objetos, pero no existe una definición rígida de qué objetos reales se pueden usar con estas reglas. La CT en sí misma se puede formalizar con CT. HMVC es un buen ejemplo de esa idea, ya que puede usar MVC dentro de MVC (aunque no es el mismo tipo de recursión).
didierc
1
También hay otras reglas que dictan cómo deben escribirse las cosas: SECO, SÓLIDO, BESO. No están en conflicto con MVC, y ciertamente deberían aplicarse tanto (si no más).
didierc

Respuestas:

6

La clave para comprender MVC radica en la separación de las responsabilidades, ya que MVC es simplemente SRP aplicado al código de UI. Separa qué datos deben mostrarse, cómo mostrarlos y cómo manejar eventos de pantalla. Pero un detalle importante (y a menudo perdido) de la definición original de MVC es que fue diseñado para un nivel mucho más granular. Por ejemplo, tendría objetos ButtonModel, ButtonView y ButtonController, "solo" para presentar un solo botón en una pantalla. Perder este detalle es lo que causa tantas opiniones diferentes sobre el tema. Puede consultar la arquitectura Java Swing para ver a qué me refiero.

El objetivo de MVC es permitir que el código que sirve a cada responsabilidad se cambie sin afectar el código para los demás. Por ejemplo, podría cambiar la representación de (un componente en) la pantalla sin tener que tocar la representación de datos ni la lógica de manejo de eventos. Entonces, hasta cierto punto, esto va de la mano con lo que dices aquí:

A partir de esto, razoné que dado cualquier Modelo y Vista, intercambiar solo el controlador no debería cambiar los datos que la página presenta inicialmente porque el controlador debería cambiar solo el comportamiento y no el 'contenido' de la página. Creo que esto se alinea con la visualización conceptual del controlador como un 'controlador de estación' en un sistema ferroviario, un plan de la vía ferroviaria como modelo y la manifestación física real y la apariencia / sensación de las pistas (en diferentes sabores, digamos ' Real 'o' Virtual 3D ') como la vista.

Sin embargo, en su contexto, el nivel de granularidad está desactivado; tiene un SessionView que parece ser responsable de una pantalla completa. En este nivel, las responsabilidades se acoplan demasiado como para separarse por completo según lo previsto por MVC, por lo que es posible que no proporcione todos los beneficios.

Su problema es separar las tres responsabilidades de la interfaz de usuario (representación, manejo de datos y eventos) para las sesiones y los procesos, un total de seis. Debido al nivel de granularidad de los componentes (pantalla completa), esto se vuelve imposible y causa la disonancia en la que se encuentran.

Desea separar las responsabilidades de procesamiento y gestión de eventos tanto para Sesiones como para Procesos, pero uniría sus datos. Su colega quiere desacoplar los datos, pero combina el manejo de eventos.

Entonces, al final, este es un problema de SRP. Mi salida sería disminuir el nivel de granularidad hasta un punto en el que pueda separar claramente las Sesiones de los Procesos. Si no puede hacer eso debido a la economía, simplemente tienen que sopesar ambos lados de la compensación, elegir lo peor y firmar como deuda técnica. Esto es, después de todo, de lo que se tratan las decisiones de diseño. :)

MichelHenrich
fuente
Gracias por su tiempo y comentario bien pensado. ¡Tenemos mucho en qué pensar aquí! Espero que no te importe si dejo esto abierto por un tiempo antes de elegir una respuesta para no desanimar a otros de compartir su POV.
kvanberendonck
Estaba pensando en esto hoy y me encontré con una pregunta interesante: ¿qué aspecto tiene el renderizado si los procesos están en el modelo de sesión? ¿Cómo un SessionView obtiene acceso a los ProcessControllers para entregar a ProcessView?
kvanberendonck
1
Bueno, con MVC, o separa las sesiones de los procesos por completo (más granular que su ejemplo), o crea un único modelo, vista y controlador para toda la pantalla, y trata las sesiones y procesos como una gran cosa (más general). Su problema es la granularidad actual de sus objetos, donde intenta separar las cosas, pero no permite una separación limpia. Otros patrones, como MVP o MVVM, funcionan mejor para "pantallas completas", a diferencia de MVC, que está destinado a los elementos pequeños en la pantalla.
MichelHenrich