Я думаю, что терминология, используемая в Qt с элементами управления модель / представление, ошибочна. На своей странице объяснения они заявляют, что они упростили MVC до MV, объединив View и Controller, и дают следующую картину:
Однако я думаю, что они неправильно назвали роли объектов, и я думаю, что
- То, что они называют представлением с объединенным контроллером, на самом деле является только представлением.
- То, что они называют моделью, на самом деле является только контроллером.
- Если вы действительно хотите иметь модель, она будет где-то там, где находятся их «Данные».
Я говорю об обычном и разумном способе использования компонента модель / представление Qt в своем приложении. Вот причины:
- Обычно это компонент Qt, который используется как есть, без добавления какой-либо логики контроллера, специфичной для ваших объектов)
- Вряд ли это Модель, просто потому, что вы должны реализовать несколько методов Qt, таких как rowCount, columnCount, data и т. Д., Которые не имеют ничего общего с вашей моделью. На самом деле в контроллерах есть типичные методы модели. Конечно, вы можете реализовать здесь логику контроллера и модели, но, во-первых, это будет довольно плохой дизайн кода, а во-вторых, вы должны объединить контроллер и модель, а не контроллер и представление, как они заявляют.
- Как сказано в причине 2. Если вы хотите разделить логику модели, это, конечно же, не синий прямоугольник на картинке, а пунктирный прямоугольник «Данные» (конечно же, сообщающийся с реальными данными).
Qt ошибается в их терминологии, или это просто я не понимаю? (Кстати: причина, по которой это не академический вопрос, заключается в том, что я начал кодировать свой проект, следуя их названию, и вскоре обнаружил, что код явно неправильный. И только после этого я понял, что я должен не пытайтесь поместить логику модели в то, что они называют моделью)
Ответы:
Я согласен с вами в том, что название Qt вводит в заблуждение. Однако, на мой взгляд, проблема заключается не только в Qt, но и во всех фреймворках, которые позволяют нам придерживаться принципа разделения задач при реализации наших пользовательских интерфейсов. Когда кто-то придумывает такую структуру и находит хороший способ разделить «вещи», он всегда чувствует себя обязанным иметь модули, которые они называют «Модель», и другие, которые они называют «Представлением». На протяжении многих лет я работал с этими фреймворками:
Если вы сравните, как термины «Модель» и «Представление» используются в этих фреймворках, и какие обязанности имеют классы в «Представлении», «Модель» и «Контроллер» (если он есть), вы увидите обнаружите, что есть очень большие различия. Безусловно, было бы полезно сравнить различные концепции и терминологию, чтобы люди, переходящие с одного фреймворка на другой, имели шанс оставаться в здравом уме, но для этого потребуется много работы и исследований. Хорошее прочтение - обзор Мартина Фаулера .
Поскольку существует так много различных идей , что шаблон MVC может выглядеть, какой из них правильный? На мой взгляд, следует обращаться к людям, которые изобрели MVC, когда мы хотим знать, как это должно быть «правильно» реализовано. В оригинальной статье о smalltalk сказано:
В свете этого я бы ответил на ваши три основные проблемы следующим образом:
Куда он нас денется? На мой взгляд, лучше всего понять, что на самом деле означает Qt, когда используются термины «Модель» и «Представление», и использовать эти термины в их манере, пока мы программируем с Qt. Если вы продолжаете беспокоиться, это только замедлит вас, а то, как все устроено в Qt, позволяет элегантный дизайн, который весит больше, чем их «неправильные» соглашения об именах.
источник
Короткий ответ
Qt MVC применяется только к одной структуре данных . Говоря о приложении MVC, не следует думать о
QAbstractItemModel
илиQListView
.Если вам нужна архитектура MVC для всей программы, Qt не имеет такой «огромной» структуры модели / представления. Но для каждого списка / дерева данных в вашей программе вы можете использовать подход Qt MVC, который действительно имеет контроллер в своем представлении. Данные внутри или вне модели; это зависит от того, какой тип модели вы используете (собственный подкласс модели: возможно, внутри модели; например, QSqlTableModel: вне (но, возможно, кэшируется внутри) модели). Чтобы объединить ваши модели и представления, используйте собственные классы, которые затем реализуют бизнес-логику .
Длинный ответ
Подход и терминология Qt модель / представление:
Qt предоставляет простые представления для своих моделей. У них есть встроенный контроллер : выбор, редактирование и перемещение элементов - это то, что в большинстве случаев «контролирует» контроллер. То есть интерпретация пользовательского ввода (щелчки и перемещение мыши) и передача модели соответствующих команд.
Модели Qt действительно являются моделями, имеющими базовые данные. Абстрактные модели, конечно, не содержат данных, поскольку Qt не знает, как вы хотите их хранить. Но вы расширяете QAbstractItemModel под свои нужды, добавляя контейнеры данных в подкласс и делая интерфейс модели доступным к вашим данным. На самом деле, и я полагаю, вам это не нравится, проблема в том, что вам нужно запрограммировать модель, а именно, как данные доступны и изменяются в вашей структуре данных.
В терминологии MVC модель содержит как данные, так и логику . В Qt вам решать, включать ли вы часть своей бизнес-логики в свою модель или размещать ее снаружи, являясь «представлением» само по себе. Непонятно даже, что подразумевается под логикой: выбор, переименование и перемещение элементов? => уже реализовано. Делаете с ними расчеты? => Поместите его вне или внутри подкласса модели. Хранение или загрузка данных из / в файл? => Поместите его в подкласс модели.
Мое личное мнение:
Очень сложно предоставить программисту хорошую и универсальную систему MV (C). Поскольку в большинстве случаев модели просты (например, только списки строк), Qt также предоставляет готовую к использованию модель QStringListModel. Но если ваши данные сложнее, чем строки, вам решать, как вы хотите представлять данные через интерфейс модель / представление Qt. Если у вас есть, например, структура с 3 полями (скажем, лица с именем, возрастом и полом), вы можете назначить 3 поля 3 различным столбцам или 3 различным ролям. Мне не нравятся оба подхода.
Я думаю, что структура модели / представления Qt полезна только тогда, когда вы хотите отображать простые структуры данных . Сложно обрабатывать, если данные относятся к настраиваемым типам или структурированы не в виде дерева или списка (например, графика). В большинстве случаев списков достаточно, и даже в некоторых случаях модель должна содержать только одну единственную запись. Особенно если вы хотите смоделировать одну единственную запись с разными атрибутами (один экземпляр одного класса), структура модели / представления Qt не является правильным способом отделения логики от пользовательского интерфейса.
Подводя итог, я считаю, что структура модели / представления Qt полезна тогда и только тогда, когда ваши данные просматриваются одним из виджетов средства просмотра Qt . Совершенно бесполезно, если вы собираетесь написать свою собственную программу просмотра для модели, содержащей только одну запись, например, настройки вашего приложения, или если ваши данные не относятся к типам для печати.
Как я использовал модель / представление Qt в (более крупном) приложении?
Однажды я написал (в команде) приложение, которое использует несколько моделей Qt для управления данными. Мы решили создать
DataRole
для хранения фактических данных, которые были разных настраиваемых типов для каждого подкласса модели. Мы создали внешний класс модели, которыйModel
содержит все различные модели Qt. Мы также создали класс внешнего вида, называемыйView
удерживающим окна (виджеты), которые связаны с моделями внутриModel
. Итак, этот подход представляет собой расширенный Qt MVC, адаптированный к нашим собственным потребностям. ОбаModel
иView
классы сами по себе не имеют ничего общего с Qt MVC.Куда мы поместили логику ? Мы создали классы, которые выполняли фактические вычисления с данными, считывая данные из исходных моделей (когда они менялись) и записывая результаты в целевые модели. С точки зрения Qt, эти классы логики будут представлениями, поскольку они «подключаются» к моделям (не «представление» для пользователя, а «представление» для части бизнес-логики приложения).
Где контроллеры ? В исходной терминологии MVC контроллеры интерпретируют пользовательский ввод (мышь и клавиатура) и дают модели команды для выполнения запрошенного действия. Поскольку представления Qt уже интерпретируют вводимые пользователем данные, такие как переименование и перемещение элементов, в этом не было необходимости. Но нам нужна была интерпретация взаимодействия с пользователем, выходящая за рамки представлений Qt.
источник
View
класс вам следует добавить модель прокси, которая имеет модель дерева в качестве базовой модели и используется представлением списка вашей файловой системы. Как вы говорите: не должно быть двух моделей для одних и тех же данных. Никогда! (Но прокси-модели не считаются отдельными моделями.)QAbstractItemModel
, некоторые из которых являются моделями в смысле MVC, а некоторые нет.Терминология неправильная или неправильная, полезная или бесполезная.
Вы можете немного изменить вопрос и спросить, почему Qt не более дружелюбен к MVC. Ответ заключается в том, что первые разработчики Qt полагают, что разделение V и C в приложениях с графическим интерфейсом создает плохие V и C. Дизайн QWidget пытается упростить привязку взаимодействия ввода мыши с решениями вывода пикселей, и вы можете видеть, что это не путь к MVC.
источник
Поскольку функция модели предназначена для ответа на запросы информации, я думаю, что нет ничего плохого в определении таких методов, как
rowCount
,columnCount
и т. Д. Я думаю, что модель - это своего рода оболочка для источника данных (независимо от того, что это таблица SQL или просто массив) , он предоставляет данные в стандартной форме, и вы должны определять методы в зависимости от структуры вашего источника данных.источник
Я считаю, что их терминология верна ... хотя я считаю, что в реальных приложениях очень легко размыть границы между моделью, представлением и контроллером в зависимости от вашего уровня абстракции: представление одного уровня может быть моделью более высокого уровня.
Я чувствую, что путаница возникает из-за их класса QAbstractModelItem. Этот класс не является элементом модели, а скорее является интерфейсом к модели. Чтобы их классы представления взаимодействовали с моделью, им пришлось создать общий абстрактный интерфейс для модели. Однако модель может быть отдельным элементом, списком элементов, таблицей с двумя или более измерениями элементов и т. Д .; поэтому их интерфейс должен поддерживать все эти варианты моделей. По общему признанию, это делает элементы модели довольно сложными, и связующий код, заставляющий их работать с реальной моделью, похоже, немного расширяет метафору.
источник
Нет, их «модель» - это точно не контроллер.
Контроллер является частью видимых пользователем элементов управления, которые изменяют модель (и, следовательно, косвенно изменяют представление). Например, кнопка «удалить» является частью контроллера.
Я думаю, что часто возникает путаница, потому что многие видят что-то вроде «контроллер изменяет модель» и думают, что это означает изменяющие функции в их модели, такие как метод «deleteRow ()». Но в классическом MVC контроллер - это именно часть пользовательского интерфейса. Методы, которые изменяют модель, являются просто частью модели.
С момента изобретения MVC различие между контроллером и представлением становится все более напряженным. Подумайте о текстовом поле: оно одновременно показывает вам текст и позволяет редактировать его, так что это вид или контроллер? Ответ должен заключаться в том, что он является частью обоих. Когда в 1960-х годах вы работали над телетайпом, различие было более четким - подумайте
ed
- но это не значит, что тогда для пользователя все было лучше!Это правда, что их QAbstractItemModel находится на более высоком уровне, чем модель обычно. Например, элементы в нем могут иметь цвет фона (технически кисть), что явно является атрибутом вида! Итак, есть аргумент, что QAbstractItemModel больше похож на представление, а ваши данные - это модель. На самом деле это что-то среднее между классическими значениями представления и модели. Но я не понимаю, как это контроллер; во всяком случае, это виджет QT, который его использует.
источник