Eu acho que a terminologia usada no Qt com controles de modelo / visão é falha. Em sua página de explicação, eles afirmam que simplificaram o MVC para MV ao fundir a Visualização e o Controlador e estão apresentando a seguinte imagem:
No entanto, eu acho que eles nomearam erroneamente as funções dos objetos e acho que,
- O que eles chamam de Visualização com controlador mesclado é, na verdade, apenas Visualização.
- O que eles chamam de modelo é, na verdade, apenas controlador.
- Se você realmente deseja ter um modelo, ele deve estar em algum lugar onde estão os seus "Dados".
Estou falando sobre a maneira normal e sensata de usar o componente de modelo / visualização Qt em seu aplicativo. Aqui estão as razões:
- Este é tipicamente o componente Qt que é usado como está, sem adicionar qualquer lógica de controlador específica para seus objetos)
- Isso dificilmente é um modelo, apenas porque você deve implementar vários métodos Qt como rowCount, columnCount, dados etc. que não têm nada a ver com seu modelo. Na verdade, existem métodos de modelo típicos encontrados em controladores. Claro, você pode implementar a lógica do controlador e do modelo aqui, mas primeiro seria um design de código muito ruim e, em segundo lugar, você mesclaria controlador e modelo, não controlador e visualização como eles afirmam.
- Como dito na razão 2. se você quiser separar a lógica do modelo, certamente não é a caixa azul na imagem, mas sim a caixa "Dados" tracejada (comunicando-se com dados reais, é claro).
O Qt está errado em sua terminologia ou sou só eu que não entendo? (A propósito: a razão pela qual não é uma questão acadêmica é que eu comecei a codificar meu projeto seguindo sua nomenclatura e logo descobri que o código claramente não está certo. Foi só depois disso que percebi que deveria não tente colocar a lógica do modelo no que eles chamam de modelo)
fonte
Respostas:
Eu concordo com você que a nomenclatura do Qt é enganosa. Na minha opinião, entretanto, o problema não é apenas do Qt, mas é compartilhado por todos os frameworks que nos permitem aderir ao princípio de separação de interesses ao implementar nossas UIs. Quando alguém surge com tal estrutura e encontra uma boa maneira de manter "coisas" separadas, sempre se sente obrigado a ter módulos que chama de "Modelo" e outros que chama de "Visualização". Ao longo dos anos, trabalhei com estas estruturas:
Se você comparar como os termos "Model" e "View" são usados nestes frameworks, e quais responsabilidades as classes em "View", "Model" e "Controller" (se houver) têm, você irá descobrir que existem diferenças muito grandes. Certamente seria útil ter uma comparação dos diferentes conceitos e terminologias, para que as pessoas que mudam de uma estrutura para outra tenham a chance de permanecer sãs, mas isso exigiria muito trabalho e pesquisa. Uma boa leitura é a visão geral de Martin Fowler .
Uma vez que existem tantas idéias diferentes como um padrão MVC pode se parecer, qual é a correta? Na minha opinião, as pessoas que inventaram o MVC devem ser consultadas quando quisermos saber como ele deve ser implementado "corretamente". No papel smalltalk original diz:
À luz disso, eu responderia às suas três principais preocupações da seguinte maneira:
Onde isso nos deixa? Na minha opinião, é melhor descobrir o que o Qt realmente significa quando os termos "Modelar" e "Visualizar" são usados e usar os termos de sua maneira enquanto estamos programando com o Qt. Se você continuar sendo incomodado, isso apenas o deixará mais lento, e a maneira como as coisas são configuradas no Qt permite um design elegante - que pesa mais do que suas convenções de nomenclatura "erradas".
fonte
Resposta curta
O MVC do Qt só se aplica a uma estrutura de dados . Ao falar sobre um aplicativo MVC , você não deve pensar em
QAbstractItemModel
ouQListView
.Se você deseja uma arquitetura MVC para todo o seu programa, o Qt não possui uma estrutura de modelo / visualização tão "grande". Mas para cada lista / árvore de dados em seu programa, você pode usar a abordagem Qt MVC, que de fato tem um controlador em sua visualização. Os dados estão dentro ou fora do modelo; isso depende de que tipo de modelo você está usando (própria subclasse de modelo: provavelmente dentro do modelo; por exemplo, QSqlTableModel: fora (mas talvez em cache dentro) do modelo). Para colocar seus modelos e visualizações juntos, use as próprias classes que implementam a lógica de negócios .
Resposta longa
Abordagem e terminologia do modelo / visão do Qt:
Qt fornece visualizações simples para seus modelos. Eles têm um controlador embutido: selecionar, editar e mover itens é algo que na maioria dos casos um controlador "controla". Ou seja, interpretar a entrada do usuário (cliques e movimentos do mouse) e fornecer os comandos apropriados ao modelo.
Os modelos do Qt são de fato modelos com dados subjacentes. Os modelos abstratos obviamente não armazenam dados, já que o Qt não sabe como você deseja armazená-los. Mas você estende um QAbstractItemModel às suas necessidades adicionando seus contêineres de dados à subclasse e tornando a interface do modelo acessando seus dados. Então, na verdade, e suponho que você não goste disso, o problema é que você precisa programar o modelo, então como os dados são acessados e modificados em sua estrutura de dados.
Na terminologia MVC, o modelo contém os dados e a lógica . No Qt, depende de você incluir ou não parte de sua lógica de negócios dentro de seu modelo ou colocá-la fora, sendo uma "visão" por si só. Não está nem claro o que se entende por lógica: selecionar, renomear e mover itens? => já implementado. Fazendo cálculos com eles? => Colocar fora ou dentro da subclasse do modelo. Armazenando ou carregando dados de / para um arquivo? => Colocar dentro da subclasse do modelo.
Minha opinião pessoal:
É muito difícil fornecer um sistema MV (C) bom e genérico para um programador. Como na maioria dos casos os modelos são simples (por exemplo, apenas listas de strings), o Qt também fornece um QStringListModel pronto para usar. Mas se seus dados são mais complexos do que strings, você decide como deseja representar os dados por meio da interface de modelo / visualização Qt. Se você tem, por exemplo, uma estrutura com 3 campos (digamos pessoas com nome, idade e sexo), você pode atribuir os 3 campos a 3 colunas diferentes ou a 3 papéis diferentes. Não gosto de ambas as abordagens.
Acho que a estrutura de modelo / visualização do Qt só é útil quando você deseja exibir estruturas de dados simples . Torna-se difícil de manusear se os dados são de tipos personalizados ou não estruturados em uma árvore ou lista (por exemplo, um gráfico). Na maioria dos casos, as listas são suficientes e, mesmo em alguns casos, um modelo deve conter apenas uma única entrada. Especialmente se você deseja modelar uma única entrada com atributos diferentes (uma instância de uma classe), a estrutura de modelo / visualização do Qt não é a maneira certa de separar a lógica da interface do usuário.
Para resumir as coisas, eu acho que o framework de model / view do Qt é útil se e somente se seus dados estão sendo vistos por um dos widgets do viewer do Qt . É totalmente inútil se você estiver prestes a escrever seu próprio visualizador para um modelo contendo apenas uma entrada, por exemplo, as configurações do seu aplicativo, ou se seus dados não forem do tipo imprimível.
Como usei o modelo / visão Qt em um aplicativo (maior)?
Certa vez, escrevi (em equipe) um aplicativo que usa vários modelos Qt para gerenciar dados. Decidimos criar um
DataRole
para conter os dados reais, que eram de um tipo personalizado diferente para cada subclasse de modelo diferente. Criamos uma classe de modelo externo chamadaModel
contendo todos os diferentes modelos Qt. Também criamos uma classe de visualização externa chamadaView
segurando as janelas (widgets) que estão conectadas aos modelos internosModel
. Portanto, esta abordagem é um Qt MVC estendido, adaptado às nossas próprias necessidades. Ambas as classesModel
eView
não têm nada a ver com o Qt MVC.Onde colocamos a lógica ? Criamos classes que faziam os cálculos reais nos dados lendo os dados dos modelos de origem (quando eram alterados) e gravando os resultados nos modelos de destino. Do ponto de vista do Qt, essas classes lógicas seriam visualizações, uma vez que "se conectam" aos modelos (não "visualização" para o usuário, mas uma "visualização" para a parte lógica de negócios do aplicativo).
Onde estão os controladores ? Na terminologia MVC original, os controladores interpretam a entrada do usuário (mouse e teclado) e dão comandos ao modelo para executar a ação solicitada. Como as visualizações do Qt já interpretam a entrada do usuário como renomear e mover itens, isso não era necessário. Mas o que precisávamos era de uma interpretação da interação do usuário que fosse além das visualizações do Qt.
fonte
View
classe "grande", você deve adicionar o modelo de proxy, que tem o modelo de árvore como modelo subjacente e é usado pela exibição de lista do sistema de arquivos. Como você está dizendo: não deve haver dois modelos para os mesmos dados. Nunca! (Mas modelos de proxy não contam como modelos separados.)QAbstractItemModel
, algumas das quais são modelos no sentido de MVC e outras não.A terminologia não é certa ou errada, é útil ou inútil.
Você pode mudar um pouco a questão e perguntar por que o Qt não é mais amigável com MVC. A resposta é que os primeiros desenvolvedores do Qt acreditam que desacoplar V de C em aplicativos GUI prejudica Vs e Cs. O design do QWidget tenta simplificar a vinculação da interação de entrada do mouse com as decisões de saída de pixel, e você pode ver como esse não é o caminho para o MVC.
fonte
Como a função de Model é responder a solicitações de informações, acho que não há nada de errado em definir métodos como
rowCount
,columnCount
etc. Acho que Model é algum tipo de invólucro para fonte de dados (não importa o que seja uma tabela SQL ou apenas um array) , ele fornece dados no formato padrão, e você deve definir os métodos de acordo com a estrutura da fonte de dados.fonte
Eu acredito que a terminologia deles está correta ... embora em aplicações reais eu ache que pode ser muito fácil borrar as linhas entre o modelo, a visão e o controlador dependendo do seu nível de abstração: a visão de um nível pode ser o modelo de um nível superior.
Acho que a confusão surge de sua classe QAbstractModelItem. Esta classe não é um item de modelo, mas sim uma interface para um modelo. Para fazer a interface de suas classes de visualização com o modelo, eles tiveram que criar uma interface abstrata genérica para o modelo. Porém, um modelo pode ser um único item, uma lista de itens, uma tabela de 2 ou mais dimensões de itens, etc; portanto, sua interface deve suportar todas essas variações de modelo. Reconhecidamente, isso torna os itens do modelo bastante complexos, e o código-cola para fazê-lo funcionar com um modelo real parece esticar um pouco a metáfora.
fonte
Não, seu "modelo" definitivamente não é um controlador.
O controlador é a parte dos controles visíveis do usuário que modificam o modelo (e, portanto, modificam indiretamente a visualização). Por exemplo, um botão "excluir" faz parte do controlador.
Acho que muitas vezes há confusão porque muitos veem algo como "o controlador modifica o modelo" e acham que isso significa as funções mutantes em seu modelo, como um método "deleteRow ()". Mas no MVC clássico, o controlador é especificamente a parte da interface do usuário. Os métodos que alteram o modelo são simplesmente parte do modelo.
Desde que o MVC foi inventado, sua distinção entre controlador e visualização tornou-se cada vez mais tensa. Pense em uma caixa de texto: ela mostra algum texto e permite que você edite, então é uma visualização ou controlador? A resposta tem que ser que faz parte de ambos. Quando você estava trabalhando em um teletipo na década de 1960, a distinção era mais clara - pense no
ed
- mas isso não significa que as coisas eram melhores para o usuário naquela época!É verdade que seu QAbstractItemModel é um nível bastante mais alto do que um modelo normalmente seria. Por exemplo, os itens nele podem ter uma cor de fundo (um pincel, tecnicamente), o que é decididamente um atributo visual! Portanto, há um argumento de que QAbstractItemModel é mais como uma visualização e seus dados são o modelo. A verdade é que está em algum lugar entre os significados clássicos de visão e modelo. Mas não consigo ver como é um controlador; se alguma coisa é o widget QT que o usa.
fonte