21
июля

Классический MVC

Написал    в категории  Программирование

Это мой вольный перевод статьи Била Сандерса о реализации классического мета паттерна MVC на Smalltalk-80. Так как это мой первый опыт, строго не судите и в комментариях желательно оставлять какие либо замечания по тексту. Переводил не дословно, немного из русскоязычных источников накопал (и каюсь, перевёл не всё).

Это не введение в модель MVC, а  обзор его осуществления на Smalltalk-80 для понимания первоначальных намерений и функций триады. Классическая MVC поможет лучше понять последующее развитие  паттернов, которые появились позже. Посмотрим, как простое MVC приложение работает в Smalltalk-80 и изучим как оно может быть реализовано на языке ActionScript.

Model-view-controller (MVC, «Модель-представление-поведение», «Модель-представление-контроллер») — архитектура программного обеспечения, в которой модель данных приложения, пользовательский интерфейс и управляющая логика разделены на три отдельных компонента, так, что модификация одного из компонентов оказывает минимальное воздействие на другие компоненты.

Современный вид MVC.

Реализация Model-View-Controller в Smalltalk-80.

Модель MVC облегчает разделение ответственности при разработке интерактивных графических приложений. Логика и состояние приложения, как пользователи взаимодействуют с приложением, и как состояние приложения представляется пользователю  по средствам отдельных элементов триады MVC. Smalltalk-80 использует метафору MVC, что обеспечивает встроенную поддержку для интерактивной разработки приложений. Идея заключалась в том, чтобы обеспечить набор встроенных компонентов пользовательского интерфейса, таких как кнопки, меню и списки, которые могут быть подключены к GUI приложения. Для эффективного использования этих встроенных элементов интерфейса, реализация должна была быть построена в соответствии с MVC. Давайте посмотрим на концептуальную диаграмму приложения Smalltalk-80.

Диаграмма MVC в Smalltalk-80 (Krasner & Pope)

Все объекты в Smalltalk общаться друг с другом при помощи сообщений, которые является способом вызова методов объекта. На первый взгляд, диаграмма MVC кажется немного странной. Model-View и Controller-Model имеют зависимости направленные в обе стороны. Вторым интересным аспектом было то, что пользовательский ввод идет непосредственно через контроллер. Это является существенным изменением, как правило мы ожидаем от пользователя взаимодействия с элементами интерфейса в представлении (View), а не в корнтроллере. В Smalltalk-80, все данные с устройства ввода подаются непосредственно в контроллер. Давайте кратко рассмотрим, как MVC поддерживается в Smalltalk-80.

MVC классы в Smalltalk-80.

Есть три абстрактных класса называемые Модель, Вид и Контроллер. Все конкретные реализации модели, вида и контроллера должны иметь подклассы этих абстрактных суперклассов. Давайте взглянем на классы (это сокращенное описание — см. Krasner & Pope).

  • Модель:
    абстрактный суперкласс Model реализует общую модель поведения. Он реализует механизм зависимости обслуживания. Вид может зарегистрироваться на конкретную модель чтобы стать подписчиком и получать оповещения об изменениях. Если конкретная модель рассылает свои сообщения, то они будут автоматически отправлены всем своим подписанным представлениям. Это реализация паттерна Наблюдатель (паттерн поведения объектов). Конкретная модель напрямую не знает о зависимых от него представлениях.

  • Представление:
    абстрактный суперкласс View реализует общие поведения представления. Встроенный набор компонентов подкласса представления (например, StandardSystemView — стандартное окно и TextEditorView — текстовый редактор). Представления могут быть вложенными для разработки сложного пользовательского интерфейса. Например, StandardSystemView (т.е. окна) содержит компонент представления, называемые TextEditorView.

    Каждое представление может иметь одну модель и один контроллер. Встроенный компоненты по умолчанию имеют заранее определенный класс контроллера для реализации своего стандартного поведения. Чтобы создать экземпляр компонента, вам нужно настроить свою модель и отобразить  компонент. Компонент затем будет инициализировать по умолчанию контроллер со своим экземпляром модели и регистрироваться в ней для получения сообщений. При закрытии компонента, освобождаются все вложенные компоненты. Когда представление освободилось, оно удаляет свои подписки на сообщения из модели. Если вы хотите чтобы компоненты имели своё уникальное поведения, вы можете создать свой контроллер для него.

  • Контроллер:
    абстрактный суперкласс Controller реализующий общие поведения. Каждый контроллер имеет ссылку на одну модель, один контроллер, и глобальную переменную называемую сенсор, который предоставляет интерфейс взаимодействия для устройств ввода (мышь, клавиатура). Абстрактный класс контроллера реализующий его общие поведения для определения уже конкретного контроллера и соответствующего ему представления. Если конкретное представление является активным (которое в данный момент использует пользователь), то его контроллер осуществляет управление всего пользовательского ввода.

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

Ключевые особенности реализации MVC на Smalltalk-80

  • каждый встроенный компонент (например ListBox) это представление;
  • представления могут быть вложенными;
  • каждый вид имеет соответствующий контроллер;
  • контроллер осведомляет своё представление, если оно активно;
  • активные контроллер (чье представление в данный момент активно) получает данные которые изменил пользователь при помощи устройств ввода;
  • контроллер может обновить представление (компонент) на основе действий пользователя;
  • контроллер изменяет модель на действий пользователя;
  • представление обновляет себя пир помощи наблюдателя, синхронизированного с моделью.

Сравнение компонентов пользовательского интерфейса Smalltalk-80 и Flash

Компоненты в Smalltalk-80 сделаны в соответствии с архитектурой MVC. В дополнение к ним, по умолчанию имеются классы контроллера и модели, которые могут быть использованы представлением для реализации его поведения. Например есть подкласс называемый TextHolder, который служит в качестве модели компоненту TextEditorView и соответствующий контроллер TextEditor. Поведение компонента можно перегрузить, и заменить своим.

Встроенные компоненты языка ActionScript не дают такой абстракции. В отличие от Smalltalk, во Flash пользователь взаимодействует с компонентами напрямую. Компонент реагирует на действия пользователя не посредством класса контроллера, а действие по умолчанию реализуются и осуществляются внутри самого компонента. Все они реализуют интерфейс IEventDispatcher. Есть несколько способов предотвратить поведение компонента по умолчанию (если компонент позволяет это сделать). В отличие от компонентов Smalltalk, многофункциональность контроллера во Flash, осуществляется посредством самих компонентов. По сути, обработчик компонента строит свою собственную логику и состояние. Например, рассмотрим иерархию классов AS3 компонента Button:

Package fl.controls
Class public class Button
Inheritance Button Inheritance LabelButton Inheritance BaseButton Inheritance UIComponent Inheritance Sprite Inheritance DisplayObjectContainer Inheritance InteractiveObject Inheritance DisplayObject Inheritance EventDispatcher Inheritance Object
Implements IFocusManagerComponent

Все AS3 компоненты имеют подкласс UIComponent чей родительский класс обеспечивает функциональность для управления фокусом. Это интересная дилемма при реализации классического MVC на AS 3.0. Поскольку компоненты реализуют большую часть традиционных функций контроллера, то имеет ли он какую то значимость? Лучший способ найти ответ на этот вопрос, это попытаться написать такое приложение.

Простое приложение с использованием классического MVC

В своей статье Краснер и Поуп реализуют простой пример приложения «счётчик», которое демонстрирует классический MVC. Модель хранит значение счётчика. Существует общий вид, и 3 дочерних представления: первое выводи значение счётчика (в текстовом поле), второе уменьшает значение (кнопка) и третье увеличивает значение, тоже кнопка. Попробуем разработать это приложение на языке ActionScript3.0 используя стандартные компоненты, при этом придерживаться классического MVC. Первым шагом является изучение поддерживаемых парадигм MVC в ActionScript.

Поддержка классической реализации MVC в ActionScript 3.0

Сравним основные особенности реализации в MVC Smalltalk-80 с тем, что имеется в AS3:

Smalltalk-80 ActionScript 3.0
Каждый компонент является представлением. Мы можем трактовать каждый компонент как представление.
Представления могут быть вложенными. Встроенные компоненты (v3) являются рычагами управления и не содержат слои которые могут быть вложенными. Однако, мы можем обратится к сцене (stage), как к верхнему уровню представления, который может содержать вложенные компоненты.
Каждое представление имеет соответствующий контроллер. Мы можем зарегистрировать объект (контроллер) для получения пользовательских событий от встроенных компонентов языка.
Контроллер управляет фокусом представления. Компоненты реализуют управление фокусом.
Активный контроллер получает данные пользовательского ввода. Может делать тоже самое, плюс компонент может рассылать пользовательские события зарегистрированным объектам контроллера.
Контроллер может обновить представление (компонент) на основе пользовательских действий. Компонент обновляется сам на основе пользовательских действий (это реализовано по умолчанию). Тем не менее, компоненты могут позволить предотвратить выполнение событий по умолчанию с помощью генерируемого объекта событий. Зарегистрированный контроллер может обновить компонент через свойства в передаваемых событиях.
Контроллер изменяет модель на основе пользовательского ввода. Объект контроллера может наблюдать за событиями компонента и таким образом обновлять модель.
Представление обновляет себя используя наблюдатель синхронизированный с моделью. Представление может наблюдать за моделью если оно реализует интерфейс IEventDispatcher.

Попробуем реализовать приложение счётчик на основе этих возможностей. (Исходный код и диаграммы классов вы можете посмотреть в оригинальной статье)

Положительные аспекты:

  • Разделение презентационной части сохраняются;
  • Контроллер представляет собой стратегию для обработки пользовательского ввода (или не представляет?);
  • Контроллер это общий объект, который может быть вызван несколькими представлениями.
Оставьте свой комментарий
  1. Вышел на данную новость случайно. Но я счастлив. Статья очень понравилась. Очень интересно было прочитать.


Rss Feed Tweeter button Facebook button