Pull to refresh

Martin Fowler — GUI Architectures. Часть 4

Reading time5 min
Views11K
Предыдущая часть здесь. Оригинал статьи здесь.

Model-View-Presenter (MVP)


Архитектура MVP впервые появилась в IBM и более явно проявилась в системе Taligent в 1990-ые годы. Достаточно подробно описана в работе Потеля (Potel). Идея была подхвачена разработчиками Dolphin Smalltalk. Как мы увидим позже, эти двe работы говорят не совсем об одном и том же, однако заложенная в них идея стала очень популярной. Будем ссылаться на эти два источника при описании архитектуры.

Для того, чтобы начать описывать MVP, я нахожу полезным подумать о существенных различиях между двумя столпами разработки UI. С одной стороны находятся «Формы и элементы», архитектура, являющаяся мэйнстримом UI-дизайна. С другой стороны — MVC и его производные. Модель «форм и элементов» предоставляет разработчику легко понимаемый дизайн и позволяет без особого труда проводить разделение между повторно используемыми элементами управления и бизнес-кодом приложения. Ей не хватает того, что в достатке есть у MVC — разделенного представления (Separated Presentation) и контекста программирования, обуславливаемого использованием доменной модели (Domain Model). Я воспринимаю MVP как объединение этих двух моделей, как попытку взять из них самое лучшее.

Согласно Potel, представление в MVP следует понимать как структуру элементов управления формы в модели «Форм и элементов», а любые разделения элемента управления на контроллер\представление следует убрать. Представление не должно содержать никакого поведения, определяющего, как элементу взаимодействовать с пользователем.

Это взаимодействие выносится в отдельный объект-представление (presenter). В представлении остаются основополагающие обработчики событий элементов управления, однако их назначением является передача управления в presenter.

Presenter должен определить, как ему реагировать на событие. Potel определяет это взаимодействие в терминах действий над моделью, которое происходит через систему команд и выборок. Кстати, можно взять на заметку этот подход — упаковка всех редакций модели в команду. Он позволит легко ввести поведение «Отменить/Повторить» (undo/redo).

Обратное обновление из модели в представление происходит через все ту же синхронизацию через обновитель (Observer Synchronization), которая используется в MVC.

Похожее описание определяется в работе Dolphin. В ней так же требуется наличие объекта presenter. Однако, в работе Dolphin не определяется система взаимодействия presenter с моделью. К тому же, там недвусмысленно намекается на то, что объект presenter должен иметь прямой доступ к представлению. Potel ничего не говорит о том, должен ли presenter иметь доступ к представлению или нет, но для Dolphin это поведение является очень важным, как раз из-за той проблемы в модели приложения (Application Model) с цветом отклонения, которую я описывал в предыдущем разделе. Как вы помните, оно решалось таким неуклюжим, с моей точки зрения, способом.

Одним из других ключей к пониманию MVP является осознание подхода, с которым presenter контролирует элементы в представлении. С одной стороны, Potel утверждает, что вся логика представления должна быть оставлена в представлении и presenter не должен определять отрисовку (render) модели. Господа Bower and McGlashan предлагают свое решение, которое я называю Supervising Controller. В этом решении почти вся логика представления так же определяется в представлении, однако presenter обладает возможностью влиять на эту логику в сложных сценариях. Т.е. некоторая часть логики представления может быть помещена в presenter.

К тому же, вы можете перенести полностью всю логику представления в presenter и получить то, что я называю Passive View. Изначально Passive View не являлось частью модели MVP. Эта модель появилась позже, тогда, когда люди научились решать проблемы тестирования. Я поговорю об этой модели позже, а сейчас скажу только то, что она является одним из видов MVP.

Перед тем, как определять отличие MVP от всего другого, что я описывал выше, я бы хотел сказать пару слов об упоминаемых мной работах. В них определяется разница MVP от MVC, но только не так, как ее вижу я. Potel утверждает, что контроллеры в MVC являются общими координаторами — с чем я не согласен. Dolphin много говорит о проблемах MVC, при этом под MVC они понимают модель приложения VisualWorks, а не тот классический MVC, про который говорил я. Я не виню их за это — в наше время информацию по классическому MVC не очень просто достать.

Теперь самое время рассказать об отличиях MVP от предыдущих архитектур (так как вижу их я):

  • Формы и элементы: в MVP есть модель и presenter манипулирует этой моделью при помощи синхронизации через обозреватель (Observer Synchronization), когда обновляет представление. И хотя прямой доступ к элементам управления у презентера разрешен, использовать этот доступ — плохой тон.
  • MVC: Чтобы манипулировать моделью, модель MVP использует Supervising Controller. Элементы управления передают введенные пользователем данные в Supervising Controller. Элементы управления не разделяются на представления и контроллеры. Presenter можно воспринимать как контроллер, но без начальной обработки пользовательского ввода. Важным является то, что presenter является объектом уровня формы, нежели элемента управления — по-моему, это еще большая разница.
  • Модель приложения: Представления передают события в presenter так же, как они передают их в модель приложения. Однако, представление в MVP может обновить себя непосредственно из доменной модели, т.к. presenter не является моделью представления (Presentation Model). Кроме того, presenter может иметь прямой доступ к элементам управления, что невозможно в случае с синхронизацией через обозреватель (Observer Synchronization).


Между presenter-ами MVP и контроллерами MVC наблюдается явное сходство. Presenter это всего лишь более свободная форма контроллера. В результате, много архитектур последуют пути MVP, но при этом будут использовать термин «контроллер», имея в виду presenter. Вообще говоря, использовать контроллер нужно тогда, когда решается вопрос со взаимодействием с пользовательским вводом на уровне элемента управления.



Рисунок 12: Диаграмма последовательности обновления текущего значения в модели MVP

Давайте посмотрим, как работает обновление текущего значения в примере с мороженым (рисунок 12). Начало диаграммы очень похоже на ту, что была в «формах и элементах» — пользователь вводит значение, текстовое поле посылает событие «текст изменен». Presenter слушает это событие и ловит его, после чего забирает у представления новое значение. Потом он обновляет доменный объект, который в свою очередь обозревается текстовым полем отклонения. Текстовое поле отклонения обновляет свое значение вычисленным, после чего ему назначается цвет. Цвет назначает presenter. Он читает категорию отклонения у замера и обновляет цвет у текстового поля (через прямую ссылку на элемент управления).

Подведем итоги модели MVP:

  • Взаимодействие с пользователем (события) передаются элементами управления в Supervising Controller, где происходит дальнейшая обработка.
  • Presenter координирует изменения в доменной модели.
  • Осуществление обновления представлений разными вариациями MVP осуществляются по-разному. Количество способов начинается от обновления через обозреватель (Observer Synchronization) и заканчивается ручными обновлениями каждого элемента управления presenter-ом.


Следующая часть здесь.
Tags:
Hubs:
Total votes 9: ↑9 and ↓0+9
Comments1

Articles