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

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

picture explaining Qt MVC

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

  • То, что они называют View с объединенным контроллером, фактически является только представлением.
  • То, что они называют Model, фактически является только контроллером.
  • Если вы действительно хотите иметь модель, она будет где-то там, где есть их "данные".

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

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

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

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

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

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 различным ролям. Мне не нравятся оба подхода.

Я думаю, что модель Qt model/view полезна только тогда, когда вы хотите отображать простые структуры данных. Сложно обрабатывать, если данные имеют настраиваемые типы или структурированы не в дереве или списке (например, в графике). В большинстве случаев списки достаточно и даже в некоторых случаях модель должна содержать только одну запись. Особенно, если вы хотите смоделировать одну единственную запись, имеющую разные атрибуты (один экземпляр одного класса), Qt model/view framework не является правильным способом отделить логику от пользовательского интерфейса.

Чтобы подвести итог, я думаю, что модель Qt model/view полезна тогда и только тогда, когда ваши данные просматриваются одним из виджетов Qt viewer. Это совершенно бесполезно, если вы собираетесь написать свой собственный просмотрщик для модели, содержащей только одну запись, например. ваши настройки приложения или если ваши данные не относятся к типам печати. ​​


Как я использовал модель Qt/представление в приложении (больше)?

Я однажды написал (в команде) приложение, которое использует несколько моделей Qt для управления данными. Мы решили создать DataRole для хранения фактических данных, которые были другого пользовательского типа для каждого подкласса модели. Мы создали внешний класс модели под названием Model, содержащий все различные модели Qt. Мы также создали внешний класс вида View, содержащий окна (виджеты), которые подключены к моделям в Model. Таким образом, этот подход является расширенным Qt MVC, адаптированным к нашим собственным потребностям. Оба класса Model и View сами не имеют ничего общего с Qt MVC.

Где мы поместили логику ? Мы создали классы, которые фактически вычисляли данные, считывая данные из исходных моделей (когда они менялись) и записывали результаты в целевые модели. С точки зрения Qt эти логические классы были бы представлениями, поскольку они "соединяются" с моделями (а не "вид" для пользователя, а "вид" для бизнес-логической части приложения).

Где контроллеры? В исходной терминологии MVC контроллеры интерпретируют ввод пользователя (мышь и клавиатуру) и дают команды модели для выполнения запрошенного действия. Поскольку представления Qt уже интерпретируют ввод пользователя, как переименование и перемещение элементов, это не было необходимо. Но нам нужна была интерпретация взаимодействия с пользователем, которая выходит за рамки представлений Qt.

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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