Почему Qt неправильно использует терминологию модель / представление? - PullRequest
94 голосов
/ 04 апреля 2011

Я думаю, что терминология, используемая в Qt с элементами управления модель / представление, неверна. На странице их объяснения они заявляют, что они упростили MVC до MV, объединив View и Controller, и дают следующую картину:

picture explaining Qt MVC

Однако я думаю, что они неправильно назвали роли объектов, и я думаю, что,

  1. То, что они называют View с объединенным контроллером, фактически является только View.
  2. То, что они называют Модель, фактически является только Контроллером.
  3. Если вы действительно хотите иметь модель, она будет где-то там, где их «Данные».

Я говорю об обычном и нормальном способе использования компонента Qt модель / представление в вашем приложении. Вот причины:

  1. Обычно это компонент Qt, который используется как есть, без добавления какой-либо логики контроллера, специфичной для ваших объектов)
  2. Это вряд ли модель, просто потому, что вы должны реализовать несколько методов Qt, таких как rowCount, columnCount, data и т. Д., Которые не имеют ничего общего с вашей моделью. На самом деле в контроллерах есть типичные методы моделей. Конечно, вы можете реализовать здесь и логику модели Controller и , но, во-первых, это будет очень плохой дизайн кода, а во-вторых, вы объедините Controller и Model, а не Controller и View в их состоянии.
  3. Как сказано в причине 2. Если вы хотите отделить логику модели, то это, безусловно, не синяя рамка на картинке, а пунктирная ячейка «Данные» (конечно, для связи с реальными данными).

Qt не прав в их терминологии, или только я не понимаю? (Кстати: причина, по которой это не является академическим вопросом, заключается в том, что я начал кодировать свой проект после их именования, и вскоре я обнаружил, что код явно неверен. Только после этого я понял, что должен не пытайтесь поставить модель логики в то, что они называют модель)

Ответы [ 5 ]

78 голосов
/ 19 мая 2012

Краткий ответ

MVC Qt применяется только к одной структуре данных . Говоря о приложении 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.

73 голосов
/ 25 мая 2012

Я согласен с вами, что наименование Qt вводит в заблуждение. Однако, по моему мнению, проблема не только в Qt, но разделяется всеми структурами, которые позволяют нам придерживаться принципа разделения интересов при реализации наших пользовательских интерфейсов. Когда кто-то придумывает такую ​​структуру и находит хороший способ отделить «вещи», он всегда чувствует себя обязанным иметь модули, которые они называют «Модель», и другие, которые они называют «Представление». На протяжении многих лет я работал с этими фреймворками:

  • MFC
  • Qt
  • Качели
  • SWT
  • WPF с MVVM

Если вы сравните, как термины «Модель» и «Представление» используются в этих структурах, и какие обязанности имеют классы в «Представлении», «Модели» и «Контроллере» (если они есть) , вы обнаружите, что есть очень большие различия. Конечно, было бы полезно сравнить различные концепции и терминологии, чтобы у людей, переключающихся с одной платформы на другую, была возможность оставаться в здравом уме, но это потребовало бы большой работы и исследований. Хорошее чтение - обзор Мартина Фаулера .

Поскольку существует так много разных идей, как может выглядеть модель MVC, какая из них верна? На мой взгляд, к людям, которые изобрели MVC, нужно обращаться, когда мы хотим знать, как это должно быть реализовано «правильно». На оригинальной бумаге для разговоров написано:

Представление управляет графическим и / или текстовым выводом для части растрового отображения, которая выделена для его приложения. Контроллер интерпретирует ввод от мыши и клавиатуры от пользователя, отдавая команду модели и / или представлению, чтобы измениться соответственно. Наконец, модель управляет поведением и данными домена приложения, отвечает на запросы информации о его состоянии (обычно из представления) и отвечает на инструкции по изменению состояния (обычно от контроллера).

В свете этого я бы ответил на три основных вопроса:

  1. Фактически, компонент Qt "управляет графическим выводом [...]" и "интерпретирует вводы с клавиатуры и мыши", поэтому его действительно можно было бы назвать объединенным представлением и контроллером в соответствии с приведенным выше определением.
  2. Я согласен с тем, что вы будете / будете вынуждены объединить контроллер и модель (снова в отношении определения выше).
  3. Я снова согласен. Модель должна управлять только данными домена приложения . Это то, что они называют «данными». Очевидно, что, например, работа со строками и столбцами не имеет ничего общего с нашим доменом приложений.

Куда это нас уходит? По моему мнению, лучше всего выяснить, что на самом деле означает Qt, когда используются термины «Модель» и «Вид», и использовать термины по-своему, когда мы программируем с помощью Qt. Если вы будете продолжать беспокоиться, это только замедлит вас, а то, как все настроено в Qt, допускает элегантный дизайн - что весит больше, чем их «неправильные» соглашения об именах.

12 голосов
/ 05 мая 2012

Терминология неверна или неправильна, она полезна или бесполезна.

Вы можете немного изменить вопрос и спросить, почему Qt не более дружественен к MVC. Ответ на этот вопрос заключается в том, что первые разработчики Qt считают, что разделение V и C в приложениях с графическим интерфейсом делает плохие V и C одинаковыми. Дизайн QWidget пытается упростить тесную привязку взаимодействия ввода мыши с решениями вывода пикселей, и вы можете увидеть, как это не путь к MVC.

3 голосов
/ 14 декабря 2012

Поскольку функция Model предназначена для ответа на запросы информации, я думаю, что нет ничего плохого в определении таких методов, как rowCount, columnCount и т. Д. Я думаю, что Model - это своего рода обертка для источника данных (независимо отэто таблица SQL или просто массив), она предоставляет данные в стандартной форме, и вам следует определить методы в зависимости от структуры вашего источника данных.

2 голосов
/ 11 мая 2011

Я считаю, что их терминология верна ... хотя в реальных приложениях я нахожу, что очень легко размывать границы между моделью, представлением и контроллером в зависимости от вашего уровня абстракции: представление одного уровня может быть моделью более высокого уровня.

Я чувствую, что путаница возникает из-за их класса QAbstractModelItem.Этот класс не элемент модели, а скорее интерфейс к модели.Чтобы их классы представлений взаимодействовали с моделью, им нужно было создать общий абстрактный интерфейс для модели.Однако модель может быть отдельным элементом, списком элементов, таблицей из двух или более измерений элементов и т. Д .;поэтому их интерфейс должен поддерживать все эти вариации модели.Следует признать, что это делает элементы модели довольно сложными, и склеивающий код, чтобы заставить его работать с реальной моделью, похоже, немного растягивает метафору.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...