Зачем

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

Не используя паттерны, код, описывающий логику View, жёстко связан с пользовательским интерфейсом, так как он напрямую взаимодействует с элементами на экране (прямолинейный подход). Он применим только для очень простых интерфейсов. Построение UI таким способом нарушает принцип единственной ответственности. Если UI-компонент содержит код для отображения, логики и данных, то у него есть несколько причин для изменения.

Проблемы:
  • Усложнение поддержки Изменения в UI, логике или данных повлекут за собой изменения в остальных частях. Поэтому вносить правки гораздо сложнее, что затрудняет поддержку.

  • Ухудшение тестируемости
    Код, связанный с пользовательским интерфейсом, плохо поддается модульному тестированию, потому что для этого часто требуется участие пользователя для запуска логики в UI.

  • Уменьшение возможности переиспользования
    Если UI-код смешан с кодом логики и данных, то его становится гораздо сложнее переиспользовать.

Ценность паттернов

Цель: отделить UI-код (View) от кода логики (Presenter, Controller, ViewModel и т. д.) и кода обработки данных (Model). Это позволяет каждому из них развиваться самостоятельно. Так как логика и данные отделены от отображения, то они могут быть протестированы отдельно.

MVC

Концепция

Model-View-Controller: модель-вид-контроллер. MVC — это конструкционный шаблон, который описывает способ построения структуры нашего приложения, сферы ответственности и взаимодействие каждой из частей в данной структуре.

MVC выгодно использовать там, где перерисовка всего компонента происходит каждый раз при возникновении события от пользователя.

Приложение разделяется на три основных компонента, каждый из которых отвечает за различные задачи:

Контроллер (Controller)

Основная функция — вызывать и координировать действие необходимых ресурсов и объектов, нужных для выполнения действий, задаваемых пользователем. Контроллер содержит в основном организационную логику для самого приложения.

Получает данные о нашем запросе серверу (в виде запросов HTTP GET или POST, когда пользователь нажимает на элементы интерфейса для выполнения различных действий), как-то эти данные обрабатывает (например получает значения из отправленной формы) и передает их в соответствующую для задачи Model. После обработки или получения данных он выбирает каким же именно способом отобразить данные клиенту (нужный View).

Модель (Model)

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

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

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

Вид (View)

Обеспечивает различные способы представления данных, которые получены из модели.

Посредством него выводиться данные клиенту, реализовывается интерфейс для их редактирования и многое другое.

Может быть шаблоном, который заполняется данными. Может быть несколько различных видов, и контроллер выбирает, какой подходит наилучшим образом для текущей ситуации.

.

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

Преимущества

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

  • Концепция MVC существенно уменьшает сложность больших приложений. Код получается гораздо более структурированным, и, тем самым, облегчается поддержка, тестирование и повторное использование решений.

  • Используя этот подход можно реализовать TDD, потому что можно спокойно протестировать все.

  • Единая концепция системы.

    Несомненным плюсом MVC является единая глобальная архитектура приложения. Даже в сложных системах, разработчики (как те, которые разрабатывали систему, так и вновь присоединившиеся) могут легко ориентироваться в программных блоках. Например, если возникла ошибка в логике обработки данных, разработчик сразу отбрасывает 2-блока программы (controller и view) и занимается исследованием 3-го (model). Я не раз удивлялся, насколько сильно упростилась локализация проблем.

  • Упрощен механизм отладки приложения.

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

Недостатки

  • Необходимость использования большего количества ресурсов. Сложность обусловлена тем, что все три фундаментальных блока являются абсолютно независимыми и взаимодействуют между собой исключительно путем передачи данных. Controller должен всегда загрузить (и при необходимости создать) все возможные комбинации переменных и передать их в Model. Model, в свою очередь, должен загрузить все данные для визуализации и передать их во View.
  • Усложнен механизм разделения программы на модули. В концепции MVC наличие трех блоков (Model, View, Controller) прописано жестко. Соответственно каждый функциональный модуль должен состоять из трех блоков, что в свою очередь, несколько усложняет архитектуру функциональных модулей программы.
  • Усложнен процесс расширения функционала. Недостаточно просто написать функциональный модуль и подключить его в одном месте программы. Каждый функциональный модуль должен состоять из трех частей, и каждая из этих частей должна быть подключена в соответствующем блоке.

Функции каждого блока

Сontroller:

  • загружает переменные окружения (POST/GET переменные, параметры командной строки, URL параметры и т. д.);
  • выполняет первичную обработку переменных окружения (проверка типов переменных, их наличие, установка значений по умолчанию и т. д.);
  • реализует механизмы контроля за внештатными ситуациями;
  • реализует механизмы логгирования (не аутентификации, а ведение журналов).

Model:

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

View:

  • организует механизмы визуализации результатов работы программы.

Пример

Каждое действие пользователя всегда запускает цепочку controller->model->view.

Предположим, надо разработать онлайновый книжный магазин. Давайте посмотрим, что произойдёт, когда пользователь нажмёт на категорию фэнтези для просмотра названий книг, которые имеются в нашем магазине.

У нас есть определённый контроллер для обработки всех действий, связанных с книгами (просматривать, редактировать, создавать и так далее). Давайте назовем его books_controller в нашем примере. Также нам нужна модель, например, book_model, которая обрабатывает данные и логику, связанные с позицией в магазине.

Следующий рисунок показывает, как обрабатывается запрос пользователя для просмотра списка книг по теме фэнтези:

Контроллер получает запрос пользователя [1] (запрос HTTP GET или POST). Мы можем организовать центральный контроллер, например, index, который получает запрос и вызывает books_controller.

Контроллер проверяет запрос и параметры, а затем вызывает модель (book_model), запрашивая у неё список доступных книг по теме фэнтези [2].

Модель получает данные из базы (или из другого источника, в котором хранится информация) [3], применяет фильтры и необходимую логику, а затем возвращает данные, которые представляют список книг [4].

Контроллер использует подходящий вид [5] для представления данных пользователю [6-7]. Если запрос приходит с мобильного телефона, используется вид для мобильного телефона; если пользователь использует определённое оформление интерфейса, то выбирается соответствующий вид, и так далее.

MVP

MVP был придуман немного при других условиях. Когда вы строите приложение на основе компонентного фреймворка. При этом нет необходимости постоянно пересоздавать Представление.

Задача MVP — тоже сделать Представления повторно используемыми. Для этого каждый View реализует определённый интерфейс и реализует механизм событий для обратной связи с Presenter'ом. Если рассмотреть тот же пример с формой входа в систему, то можно создать два View, один в углу приложения, другой в основном окне и подписать Presenter на события от обоих. Из пришедшего события Presenter получит отправителя и через View интерфейс получит все данные отправленные пользователем.

.

класс Presenter, в который мы выносим логику обработки событий, форматирования данных и управления View. Под View мы будем понимать слой, включающий дочерние классы UIViewController, Activity или Fragment и их связку с классами всевозможных контролов. Таким образом мы “разгружаем” классы аналогичные UIViewController от тех обязанностей, которыми они не должны заниматься, оставляя внутри только код инициализации представлений и анимаций.

Преимущества

Настоящее отделение логики представления от модели;

  1. Четкое разделение ответственности между классами:
    • View — прорисовка, анимации, переходы между экранами;
    • Presenter — форматирование, реакция на события, логика представления и управление View;
    • Model — работа с загрузкой данных по API, извлечение данных из БД и их кэширование;
  2. Практически универсальная реализация интерфейсов Model-View-Presenter-а на мобильных платформах для “обычных” проектов;
  3. Интеграционное тестирование на уровне Presenter-а;
  4. Разделение задач в команде в рамках разработки одного экрана на задачи представления (вместе с Presenter-ом) и модели;
  5. Возможность показа интерактивного демо заказчику, без работающего бэкенда. При появлении реального сервиса мы не выбрасываем весь код, который написали, а адаптируем API;
  6. Возможность эффективного привлечения непрофильного разработчика из команды для написания кода на другой платформе;
  7. Расширение и добавление новых фич не вызовет эффекта “чужого кода”, когда человек возвращается к разработке проекта после длительного перерыва из-за набора простых правил размещения кода в строго определенных модулях.

Недостатки

К недостаткам можно отнести не такую быструю скорость разработки как при использовании Apple MVC или аналогичного подхода под Android. Также в конкретно представленной вариации MVP сознательно был сделан упор на один общий класс-сервис из-за простоты, но это потребует некоторых техник по его разделению.


MVVM

Шаблон MVVM имеет три основных компонента: модель, которая представляет бизнес-логику приложения, представление пользовательского интерфейса XAML, и представление-модель, в котором содержится вся логика построения графического интерфейса и ссылка на модель, поэтому он выступает в качестве модели для представления.

Признаки View-модели

  • Двухсторонняя коммуникация с представлением;
  • View-модель — это абстракция представления. Обычно свойства представления совпадают со свойствами View-модели / модели;
  • View-модель не имеет ссылки на интерфейс представления (IView). Изменение состояния View-модели автоматически изменяет представление и наоборот, поскольку используется механизм связывания данных (Bindings);
  • Один экземпляр View-модели связан с одним отображением.

Шаблон MVVM общая реализация:

Если вы планируете работать с WPF или Silverlight, вы должны воспользоваться механизмом привязок (binding), предоставляемым этими технологиями. Для этого, ваша модель-представление должна реализовать некоторые конкретные интерфейсы, необходимые модулю привязки из WPF и Silverlight. Одним из них является INotifyPropertyChanged, введенный в .NET Framework начиная с версии 2 и выше. Этот интерфейс реализует систему уведомлений которая активируется, когда значение свойства изменяется. Это требуется в модели-представления, чтобы сделать механизм привязки пользовательского интерфейса XAML динамическим.

Другой настройкой являются команды, предоставляемые интерфейсом ICommand, которые доступны для WPF и Silverlight. Команды могут привязываться к определенному XAML-элементу и определять поведение данного элемента при определенных действиях.

Третьим компонентом в показанной выше структуре является шаблон данных DataTemplate, который определяет как структурировать конкретную модель-представления или особое состояние модели-представления.

Пример

MV*

results matching ""

    No results matching ""