Creo que la terminología utilizada en Qt con controles de modelo / vista es defectuosa. En su página de explicación , afirman que simplificaron el MVC a MV fusionando View y Controller y están dando la siguiente imagen:
Sin embargo, creo que nombraron mal los roles de los objetos y creo que,
- Lo que llaman Vista con controlador fusionado es, de hecho, solo Vista.
- Lo que ellos llaman Modelo es, de hecho, solo controlador.
- Si realmente quieres tener un modelo, debería estar en algún lugar donde estén sus "Datos".
Estoy hablando de la forma habitual y sensata en que usaría el componente de vista / modelo Qt en su aplicación. Estas son las razones:
- Este es típicamente un componente Qt que se usa tal cual, sin agregar ninguna lógica de controlador específica a sus objetos)
- Esto no es un modelo, solo porque debe implementar varios métodos Qt como rowCount, columnCount, datos, etc.que no tienen nada que ver con su modelo. De hecho, hay métodos de modelo típicos que se encuentran en Controllers. Por supuesto, puede implementar tanto la lógica del controlador como la del modelo aquí, pero primero sería un diseño de código bastante malo y, en segundo lugar, combinaría el controlador y el modelo, no el controlador y la vista como se indica.
- Como se dijo en la razón 2, si desea separar la lógica del modelo, seguramente no es el cuadro azul de la imagen, sino el cuadro de "Datos" discontinuo (comunicándose con los datos reales, por supuesto).
¿Qt está mal en su terminología, o soy yo quien no entiende? (Por cierto: la razón por la que no es una cuestión académica es que comencé a codificar mi proyecto siguiendo su nombre y pronto descubrí que el código claramente no es correcto. Fue solo después de eso cuando me di cuenta de que debería no intente poner la lógica del modelo en lo que ellos llaman Modelo)
Respuestas:
Estoy de acuerdo con usted en que el nombre de Qt es engañoso. En mi opinión, sin embargo, el problema no es solo de Qt, sino que es compartido por todos los marcos que nos permiten adherirnos al principio de separación de preocupaciones al implementar nuestras UI. Cuando a alguien se le ocurre un marco de este tipo y encuentra una buena manera de mantener "las cosas" separadas, siempre se siente obligado a tener módulos que llaman "Modelo" y otros que llaman "Vista". A lo largo de los años he trabajado con estos marcos:
Si compara cómo se usan los términos "Modelo" y "Vista" en estos marcos, y qué responsabilidades tienen las clases en la "Vista", el "Modelo" y el "Controlador" (si hay uno), obtendrá descubre que hay diferencias muy grandes. Ciertamente sería útil tener una comparación de los diferentes conceptos y terminologías, de modo que las personas que cambian de un marco a otro tengan la oportunidad de mantenerse cuerdos, pero eso requeriría mucho trabajo e investigación. Una buena lectura es la descripción general de Martin Fowler .
Dado que hay tantas ideas diferentes sobre cómo puede verse un patrón MVC, ¿cuál es la correcta? En mi opinión, deberíamos acudir a las personas que inventaron MVC cuando queramos saber cómo se supone que debe implementarse "correctamente". En el papel original de Smalltalk dice:
A la luz de eso, respondería a sus tres preocupaciones principales de la siguiente manera:
¿Dónde nos deja? En mi opinión, es mejor averiguar qué significa realmente Qt cuando se usan los términos "Modelo" y "Vista" y usar los términos a su manera mientras programamos con Qt. Si sigues molestándote, solo te ralentizará, y la forma en que están configuradas las cosas en Qt permite un diseño elegante, que pesa más que sus convenciones de nomenclatura "incorrectas".
fuente
Respuesta corta
MVC de Qt solo se aplica a una estructura de datos . Cuando se habla de una aplicación MVC , no debe pensar en
QAbstractItemModel
oQListView
.Si desea una arquitectura MVC para todo su programa, Qt no tiene un marco de modelo / vista tan "enorme". Pero para cada lista / árbol de datos en su programa, puede usar el enfoque Qt MVC que de hecho tiene un controlador a su vista. Los datos están dentro o fuera del modelo; esto depende del tipo de modelo que esté utilizando (propia subclase de modelo: probablemente dentro del modelo; por ejemplo, QSqlTableModel: fuera (pero quizás almacenado en caché) del modelo). Para unir sus modelos y vistas, use clases propias que luego implementen la lógica empresarial .
Respuesta larga
Enfoque y terminología de modelo / vista de Qt:
Qt proporciona vistas simples para sus modelos. Tienen un controlador integrado: seleccionar, editar y mover elementos es algo que en la mayoría de los casos un controlador "controla". Es decir, interpretar la entrada del usuario (clics y movimientos del mouse) y dar los comandos apropiados al modelo.
Los modelos de Qt son de hecho modelos que tienen datos subyacentes. Los modelos abstractos, por supuesto, no contienen datos, ya que Qt no sabe cómo desea almacenarlos. Pero se extiende una QAbstractItemModel a sus necesidades mediante la adición de sus contenedores de datos a la subclase y haciendo que la interfaz de modelo de acceso a sus datos. Así que, de hecho, y supongo que no lo hace así, el problema es que se necesita programar el modelo, así que ¿cómo se accede y modificados en su estructura de datos de datos.
En la terminología MVC, el modelo contiene tanto los datos como la lógica . En Qt, depende de usted si incluye o no parte de su lógica empresarial dentro de su modelo o la pone fuera, siendo una "vista" por sí misma. Ni siquiera está claro qué se entiende por lógica: ¿seleccionar, cambiar el nombre y mover elementos? => ya implementado. ¿Haciendo cálculos con ellos? => Ponlo fuera o dentro de la subclase del modelo. ¿Almacenar o cargar datos desde / hacia un archivo? => Ponlo dentro de la subclase del modelo.
Mi opinión personal:
Es muy difícil proporcionar un sistema MV (C) bueno y genérico a un programador. Debido a que en la mayoría de los casos los modelos son simples (por ejemplo, solo listas de cadenas), Qt también proporciona un QStringListModel listo para usar. Pero si sus datos son más complejos que las cadenas, depende de usted cómo desea representar los datos a través de la interfaz modelo / vista de Qt. Si tiene, por ejemplo, una estructura con 3 campos (digamos personas con nombre, edad y sexo), podría asignar los 3 campos a 3 columnas diferentes o a 3 roles diferentes. No me gustan ambos enfoques.
Creo que el marco de modelo / vista de Qt solo es útil cuando desea mostrar estructuras de datos simples . Se vuelve difícil de manejar si los datos son de tipos personalizados o no están estructurados en un árbol o lista (por ejemplo, un gráfico). En la mayoría de los casos, las listas son suficientes e incluso en algunos casos, un modelo solo debe contener una sola entrada. Especialmente si desea modelar una sola entrada con diferentes atributos (una instancia de una clase), el marco de modelo / vista de Qt no es la forma correcta de separar la lógica de la interfaz de usuario.
Para resumir, creo que el marco de modelo / vista de Qt es útil si y solo si uno de los widgets de visor de Qt está viendo sus datos . Es totalmente inútil si está a punto de escribir su propio visor para un modelo que contiene solo una entrada, por ejemplo, la configuración de su aplicación, o si sus datos no son de tipo imprimible.
¿Cómo usé el modelo / vista Qt dentro de una aplicación (más grande)?
Una vez escribí (en equipo) una aplicación que usa múltiples modelos Qt para administrar datos. Decidimos crear un
DataRole
para contener los datos reales que eran de un tipo personalizado diferente para cada subclase de modelo diferente. Creamos una clase de modelo externa llamada queModel
contiene todos los diferentes modelos de Qt. También creamos una clase de vista externa llamadaView
mantener las ventanas (widgets) que están conectadas a los modelos internosModel
. Entonces, este enfoque es un Qt MVC extendido, adaptado a nuestras propias necesidades. TantoModel
yView
clases mismas no tienen nada que ver con el Qt MVC.¿Dónde pusimos la lógica ? Creamos clases que realizaban los cálculos reales de los datos leyendo datos de los modelos de origen (cuando cambiaban) y escribiendo los resultados en los modelos de destino. Desde el punto de vista de Qt, estas clases lógicas serían vistas, ya que se "conectan" a modelos (no "vista" para el usuario, sino una "vista" para la parte lógica de negocios de la aplicación).
¿Dónde están los controladores ? En la terminología MVC original, los controladores interpretan la entrada del usuario (mouse y teclado) y dan comandos al modelo para realizar la acción solicitada. Dado que las vistas de Qt ya interpretan la entrada del usuario como cambiar el nombre y mover elementos, esto no era necesario. Pero lo que necesitábamos era una interpretación de la interacción del usuario que fuera más allá de las vistas de Qt.
fuente
View
clase "grande" , debes agregar el modelo proxy, que tiene el modelo de árbol como modelo subyacente y es utilizado por la vista de lista de tu sistema de archivos. Como está diciendo: no debería haber dos modelos para los mismos datos. ¡Nunca! (Pero los modelos proxy no cuentan como modelos separados)QAbstractItemModel
, algunas de las cuales son modelos en el sentido de MVC y otras no.La terminología no es correcta o incorrecta, es útil o inútil.
Puede cambiar un poco la pregunta y preguntar por qué Qt no es más compatible con MVC. La respuesta a es que los primeros desarrolladores de Qt creen que el desacoplamiento de V de C en las aplicaciones GUI genera Vs y Cs malas. El diseño de QWidget intenta simplificar la vinculación de la interacción de entrada del mouse con las decisiones de salida de píxeles, y puede ver cómo ese no es el camino hacia MVC.
fuente
Como la función del modelo es responder a las solicitudes de información, creo que no hay nada de malo en definir métodos como
rowCount
,columnCount
etc. Creo que el modelo es una especie de contenedor para la fuente de datos (no importa qué es una tabla SQL o simplemente una matriz) , proporciona datos en forma estándar, y debería definir métodos dependiendo de la estructura de su fuente de datos.fuente
Creo que su terminología es correcta ... aunque en aplicaciones reales encuentro que puede ser muy fácil difuminar las líneas entre modelo, vista y controlador dependiendo de su nivel de abstracción: la vista de un nivel puede ser el modelo de un nivel superior.
Siento que la confusión surge de su clase QAbstractModelItem. Esta clase no es un elemento de modelo, sino más bien una interfaz para un modelo. Para hacer que sus clases de vista interactúen con el modelo, tuvieron que crear una interfaz abstracta genérica para el modelo. Sin embargo, un modelo puede ser un solo elemento, una lista de elementos, una tabla de 2 o más dimensiones de elementos, etc; por lo que su interfaz debe admitir todas estas variaciones de modelos. Es cierto que esto hace que los elementos del modelo sean bastante complejos, y el código adhesivo para que funcione con un modelo real parece estirar un poco la metáfora.
fuente
No, su "modelo" definitivamente no es un controlador.
El controlador es la parte de los controles visibles para el usuario que modifican el modelo (y por tanto modifican indirectamente la vista). Por ejemplo, un botón "eliminar" es parte del controlador.
Creo que a menudo hay confusión porque muchos ven algo como "el controlador modifica el modelo" y piensan que esto significa las funciones mutantes en su modelo, como un método "deleteRow ()". Pero en MVC clásico, el controlador es específicamente la parte de la interfaz de usuario. Los métodos que mutan el modelo son simplemente parte del modelo.
Desde que se inventó MVC, su distinción entre controlador y vista se ha vuelto cada vez más tensa. Piense en un cuadro de texto: le muestra algo de texto y le permite editarlo, entonces, ¿es vista o controlador? La respuesta tiene que ser que es parte de ambos. Cuando trabajaba en un teletipo en la década de 1960, la distinción era más clara, piense en el
ed
, ¡pero eso no significa que las cosas fueran mejores para el usuario en ese entonces!Es cierto que su QAbstractItemModel es de un nivel bastante superior al que normalmente tendría un modelo. Por ejemplo, los elementos en él pueden tener un color de fondo (técnicamente un pincel), ¡que es un atributo decididamente visual! Entonces, hay un argumento de que QAbstractItemModel es más como una vista y sus datos son el modelo. La verdad es que está en algún lugar entre los significados clásicos de vista y modelo. Pero no veo cómo es un controlador; en todo caso, ese es el widget QT que lo usa.
fuente