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


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

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

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

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

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

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

5 90

5 ответов:

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

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

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

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

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

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

  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 model/view framework полезен только тогда, когда вы хотите отобразить простые структуры данных. Это становится трудно обрабатывать, если данные пользовательские типы или структурированы не в дереве или списке (например, график). В большинстве случаев, списки достаточно и даже в некоторых случаях модель должна содержать только одну запись. Особенно если вы хотите смоделировать одну единственную запись, имеющую разные атрибуты (один экземпляр одного класса), Qt структура модели/представления-это неправильный способ отделить логику от пользовательского интерфейса.

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


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

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

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

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

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

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

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

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

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