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

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

picture explaining Qt MVC

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

  1. то, что они называют представлением с объединенным контроллером, на самом деле является только представлением.
  2. что они называют моделью на самом деле только контроллер.
  3. если вы действительно хотите иметь модель, это будет где-то, где их "данные".

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

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

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

5 ответов


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

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

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

Так как есть так много разных идей, что an шаблон MVC может выглядеть так, какой из них правильный? На мой взгляд, люди, которые изобрели MVC, должны быть обращены, когда мы хотим знать, как это должно быть реализовано "правильно". В оригинал на языке Smalltalk бумага!--2--> Он говорит:

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

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

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

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


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

MVC Qt применяется только к одна структура данных. Когда речь идет о ДТП приложение вы не должны думать о QAbstractItemModel или QListView.

если вы хотите архитектуру MVC для всей вашей программы, Qt не имеет такой "огромной" структуры модели / представления. Но для каждого списка / дерева данных в вашей программе вы можете использовать подход Qt MVC, который действительно имеет контроллер в своем представлении. Этот сведения находится внутри или вне модели; это зависит от того, какой тип модели вы используете (собственный подкласс модели: вероятно, внутри модели; например, QSqlTableModel: снаружи (но, возможно, кэшируется внутри) модели). Чтобы объединить ваши модели и представления, используйте собственные классы, которые затем реализуют бизнес-логики.


ответ

подход и терминология модели/представления Qt:

Qt обеспечивает простой вид для своих моделей. У них есть контроллер встроенный: выбор, редактирование и перемещение элементов-это то, что в большинстве случаев контроллер "контролирует". То есть интерпретация пользовательского ввода (щелчки и перемещения мыши) и предоставление соответствующих команд модели.

Qt модели действительно модели, имеющие базовые данные. Абстрактные модели, конечно, не содержат данных, так как Qt не знает, как вы хотите их хранить. Но вы расширьте QAbstractItemModel для ваших нужд, добавив контейнеры данных в подкласс и сделав интерфейс модели доступом к вашим данным. Так что на самом деле, и я предполагаю, что вам это не нравится, проблема в том, что вы нужно запрограммировать модель, так как данные доступны и изменены в вашей структуре данных.

в терминологии MVC, модель содержит как сведения и логика. В Qt, это до вас ли вы включаете часть своей бизнес-логики в свою модель или помещаете ее снаружи, будучи "видом" самостоятельно. Даже не ясно, что подразумевается под логикой: выбор, переименование и перемещение элементов? => уже реализовано. Делать с ними расчеты? => Поместите его снаружи или внутри подкласса модели. Хранение и загрузка данных из/в файл? => Поместите его в подкласс модели.


мое личное мнение:

очень трудно обеспечить хороший и общая система MV(C) для программиста. Поскольку в большинстве случаев модели просты (например, только строковые списки), Qt также предоставляет готовую к использованию QStringListModel. Но если ваши данные сложнее, чем строки, вам решать, как вы хотите представлять данные через интерфейс Qt model/view. Если у вас есть, например, структура с 3 полями (скажем, люди с именем, возрастом и полом), вы можете назначить 3 поля 3 различным столбцам или 3 различным ролям. Мне не нравятся обе подходы.

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

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


как я использовал Qt model / view внутри a (большее) приложение?

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

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

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


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

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


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


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

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