JavaRush /Java блог /Java Developer /Часть 7. Знакомство с паттерном MVC (Model-View-Controlle...
Professor Hans Noodles
41 уровень

Часть 7. Знакомство с паттерном MVC (Model-View-Controller)

Статья из группы Java Developer
Этот материал — часть цикла “Введение в Enterprise-разработку”. Предыдущие статьи: Часть 7. Знакомство с паттерном MVC (Model-View-Controller) - 1В этом материале мы познакомимся с тобой с такой штукой как MVC. Поговорим о том, что такое MVC, затронем историю его создания, разберемся с основными идеями и концепциями, заложенными в MVC, рассмотрим пошагово, как разбить приложение на модули Модель, Вид, Контроллер, а также напишем небольшое веб приложение на Spring-Boot, и на примере Spring-MVC посмотрим как данные передаются из Java кода в html страницы. Чтобы понять этот материал, тебе нужно быть знакомым с шаблонами проектирования, особенно с Наблюдателем (Observer) и Фасадом (Facade). Быть знакомым с HTTP запросами и ответам, понимать основы html, знать, что такое аннотации в Java. Усаживайся поудобнее, заваривай чай, готовь десерт, салат, второе и первое. Мы начинаем.

История создания MVC

Идеи MVC сформулировал Трюгве Реенскауг (Trygve Reenskaug) во время работы в Xerox PARC в конце 70-х годов. В те времена для работы с ЭВМ было не обойтись без ученой степени и постоянного изучения объемной документации. Задача, которую Реенскауг решал совместно с группой очень сильных разработчиков, заключалась в том, чтобы упростить взаимодействие рядового пользователя с компьютером. Необходимо было создать средства, которые с одной стороны были бы предельно простыми и понятными, а с другой — давали бы возможность управлять компьютером и сложными приложениями. Реенскауг работал в команде, которая занималась разработкой портативного компьютера "для детей всех возрастов" — Dynabook, а также языка SmallTalk под руководством Алана Кея (Alan Kay). Именно тогда и там закладывались понятия дружелюбного интерфейса. Работа Реенскауга совместно с командой во многом повлияла на развитие сферы IT. Приведем интересный факт, который не относится к MVC напрямую, но иллюстрирует значимость тех разработок. В 2007 году после презентации Apple iPhone, Алан Кей сказал: “Когда вышел Macintosh, в Newsweek спросили, что я о нем думаю. Я сказал: это первый персональный компьютер, достойный критики. После презентации Стив Джобс подошел и спросил: достоин ли iPhone критики? И я ответил: сделайте его размером пять на восемь дюймов, и вы завоюете мир”. Спустя 3 года, 27 января 2010 года, Apple представила iPad диагональю 9,7 дюйма. То есть Стив Джобс почти буквально следовал совету Алана Кея. Проект, над которым работал Реннскауг велся на протяжении 10 лет. А первая публикация об MVC от его создателей вышла в свет еще через 10 лет. Мартин Фаулер, автор ряда книг и статей по архитектуре ПО, упоминает, что он изучал MVC по работающей версии SmallTalk. Поскольку информации об MVC из первоисточника долго не было, а также по ряду других причин, появилось большое количество различных трактовок этого понятия. В результате многие считают MVC схемой или паттерном проектирования. Реже MVC называют составным паттерном или комбинацией нескольких паттернов, работающих совместно для реализации сложных приложений. Но на самом деле, как было сказано ранее, MVC — это прежде всего набор архитектурных идей/принципов/подходов, которые можно реализовать различными способами с использованием различных шаблонов... Далее мы попробуем рассмотреть основные идеи, заложенные в концепции MVC.

Что такое MVC: основные идеи и принципы

  • VC — это набор архитектурных идей и принципов для построения сложных информационных систем с пользовательским интерфейсом;
  • MVC — это аббревиатура, которая расшифровывается так: Model-View-Controller.
Дисклеймер: MVC — это не паттерн проектирования. MVC — это именно набор архитектурных идей и принципов для построения сложных систем с пользовательским интерфейсом. Но для удобства, чтобы каждый раз не повторять: “Набор архитектурных идей…”, мы будем называть MVC паттерном. Начнем с простого. Что же скрывается за словами Model-View-Controller? При разработке систем с пользовательским интерфейсом, следуя паттерну MVC нужно разделять систему на три составные части. Их, в свою очередь, можно называть модулями или компонентами. Говори как хочешь, но дели на три. У каждой составной компоненты будет свое предназначение. Model. Первая компонента/модуль — так называемая модель. Она содержит всю бизнес-логику приложения. View. Вторая часть системы — вид. Данный модуль отвечает за отображение данных пользователю. Все, что видит пользователь, генерируется видом. Controller. Третьим звеном данной цепи является контроллер. В нем хранится код, который отвечает за обработку действий пользователя (любое действие пользователя в системе обрабатывается в контроллере). Модель — самая независимая часть системы. Настолько независимая, что она не должна ничего знать о модулях Вид и Контроллер. Модель настолько независима, что ее разработчики могут практически ничего не знать о Виде и Контроллере. Основное предназначение Вида — предоставлять информацию из Модели в удобном для восприятия пользователя формате. Основное ограничение Вида — он никак не должен изменять модель. Основное предназначение Контроллера — обрабатывать действия пользователя. Именно через Контроллер пользователь вносит изменения в модель. Точнее в данные, которые хранятся в модели. Приведем еще раз схему, которую тебе уже показывали на лекции: Часть 7. Знакомство с паттерном MVC (Model-View-Controller) - 2Из всего этого можно сделать вполне логичный вывод. Сложную систему нужно разбивать на модули. Опишем кратко шаги, как можно добиться подобного разделения.

Шаг 1. Отделить бизнес-логику приложения от пользовательского интерфейса

Ключевая идея MVC состоит в том, что любое приложение с пользовательским интерфейсом в первом приближении можно разбить на 2 модуля: модуль, отвечающий за реализацию бизнес-логики приложения, и пользовательский интерфейс. В первом модуле будет реализован основной функционал приложения. Данный модуль будет ядром системы, в котором реализуется модель предметной области приложения. В концепции MVC данный модуль будет нашей буковкой M, т.е. моделью. Во втором модуле будет реализован весь пользовательский интерфейс, включая отображение данных пользователю и логику взаимодействия пользователя с приложением. Основная цель такого разделения — сделать так, чтобы ядро системы (Модель в терминологии MVC) могла независимо разрабатываться и тестироваться. Архитектура приложения после подобного разделения будет выглядеть следующим образом: Часть 7. Знакомство с паттерном MVC (Model-View-Controller) - 3

Шаг 2. Используя шаблон Наблюдатель, добиться еще большей независимости модели, а также синхронизации пользовательских интерфейсов

Здесь мы преследуем 2 цели:
  1. Добиться еще большей независимости модели.
  2. Синхронизировать пользовательские интерфейсы.
Понять, что подразумевается под синхронизацией пользовательских интерфейсов, поможет следующий пример. Предположим, мы покупаем билет в кино через интернет и видим количество свободных мест в кинотеатре. Одновременно с нами покупать билет в кино может кто-то еще. Если этот кто-то купит билет раньше нас, нам бы хотелось увидеть, что количество свободных мест на наш сеанс уменьшилось. А теперь поразмышляем о том, как это может быть реализовано внутри программы. Предположим, у нас есть ядро системы (наша модель) и интерфейс (веб страница, на которой мы осуществляем покупку). На сайте 2 пользователя одновременно выбирают место. Первый пользователь купил билет. Второму пользователю необходимо отобразить на странице эту информацию. Как это должно произойти? Если мы из ядра системы будем обновлять интерфейс, наше ядро, наша модель, будет зависима от интерфейса. При разработке и тестировании модели придется держать в голове различные способы обновления интерфейса. Чтобы достичь этого, необходимо реализовать шаблон Наблюдатель. С его помощью модель рассылает уведомления об изменениях всем подписчикам. Интерфейс, являясь таким подписчиком, получит уведомление и обновится. Шаблон Наблюдатель позволяет модели с одной стороны информировать интерфейс (вид и контроллер) о том, что в ней произошли изменения, а с другой — фактически ничего о них “не знать”, и тем самым оставаться независимой. С другой стороны, это позволит синхронизировать пользовательские интерфейсы.

Шаг 3. Разделение интерфейса на Вид и Контроллер

Продолжаем делить приложение на модули, но уже на более низком уровне иерархии. На этом шаге пользовательский интерфейс (который был выделен в отдельный модуль на шаге 1) делится на вид и контроллер. Сложно провести строгую черту между видом и контроллером. Если говорить о том, что вид — это то, что видит пользователь, а контроллер — это механизм, благодаря которому пользователь может взаимодействовать с системой, можно обнаружить некоторое противоречие. Элементы управления, например, кнопки на веб-странице или виртуальная клавиатура на экране телефона, это по сути часть контроллера. Но они так же видны пользователю, как и любая часть вида. Здесь скорее речь идет о функциональном разделении. Основная задача пользовательского интерфейса — обеспечить взаимодействие пользователя с системой. Это означает, что у интерфейса всего 2 функции:
  • выводить и удобно отображать пользователю информацию о системе;
  • вводить данные и команды пользователя в систему (передавать их системе);
Данные функции и определяют то, как нужно делить интерфейс на модули. В итоге, архитектура системы выглядит так: Часть 7. Знакомство с паттерном MVC (Model-View-Controller) - 4Итак, у нас появилось приложение из трех модулей, которые называются Модель, Вид и Контроллер. Резюмируем:
  1. Следуя принципам MVC, систему нужно разделять на модули.
  2. Самым важным и независимым модулем должна быть модель.
  3. Модель — ядро системы. Нужна возможность разрабатывать и тестировать ее независимо от интерфейса.
  4. Для этого на первом шаге сегрегации системы нужно разделить ее на модель и интерфейс.
  5. Далее, с помощью шаблона Наблюдатель, укрепляем модель в ее независимости и получаем синхронизацию пользовательских интерфейсов.
  6. Третьим шагом делим интерфейс на контроллер и вид.
  7. Все, что на ввод информации от пользователя в систему — это в контроллер.
  8. Все что на вывод информации от системы к пользователю — это в вид.
Осталось обсудить еще одну важную вещь и можно пить какао.

Немного о взаимосвязи Вида и Контроллера с Моделью

Когда пользователь вводит информацию через контроллер, он тем самым вносит изменения в модель. По крайней мере, пользователь вносит изменения в данные модели. Когда пользователь получает информацию через элементы интерфейса (через Вид), пользователь получает информацию о данных модели. Как это происходит? Посредством чего Вид и Контроллер взаимодействуют с моделью? Ведь не может быть так, что классы Вида напрямую используют методы классов Модели для чтения/записи данных, иначе ни о какой независимости Модели не может быть и речи. Модель представляет тесно связанный между собой набор классов, к которым, по-хорошему, ни у Вида, ни у Контроллера не должно быть доступа. Для связи Модели с Видом и Контроллером необходимо реализовать шаблон проектирования Фасад. Фасад модели будет той самой прослойкой между Моделью и интерфейсом, через которую Вид получает данные в удобном формате, а Контроллер изменяет данные, вызывая нужные методы фасада. Схематично, в итоге, все будет выглядеть так: Часть 7. Знакомство с паттерном MVC (Model-View-Controller) - 6

MVC: в чем профит?

Основная цель следования принципам MVC — отделить реализацию бизнес-логики приложения (модели) от ее визуализации (вида). Такое разделение повысит возможность повторного использования кода. Польза применения MVC наиболее наглядна в случаях, когда пользователю нужно предоставлять одни и те же данные в разных формах. Например, в виде таблицы, графика или диаграммы (используя различные виды). При этом, не затрагивая реализацию видов, можно изменить реакции на действия пользователя (нажатие мышью на кнопке, ввод данных). Если следовать принципам MVC, можно упростить написание программ, повысить читаемость кода, сделать легче расширение и поддержку системы в будущем. В завершающем материале цикла “Введение в Enterprise-разработку” мы с тобой посмотрим на реализацию MVC на примере Spring-MVC. Часть 8. Пишем небольшое приложение на spring-boot
Комментарии (26)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
8 марта 2024
картинки только ухудшают понимание темы.
Semen Semenov Уровень 22
1 марта 2024
Кому про ошибки в стать писать?
Balsakas Уровень 23
1 ноября 2023
Про паттерны тут) https://javarush.com/groups/posts/584-patternih-proektirovanija
TemaCode Уровень 51
1 ноября 2022
" Модель — самая независимая часть системы. Настолько независимая, что она не должна ничего знать о модулях Вид и Контроллер. Модель настолько независима, что ее разработчики могут практически ничего не знать о Виде и Контроллере.."(c) -)))
FatCat Уровень 51
11 сентября 2022
Посмотрите видео по ссылке из задачи на MVC всё на свои места встанет
Igor Petrashevsky Уровень 47
8 июня 2022
В картинке MVC логично стрелку "смотрит" не от юзера, а к юзеру повернуть. Юзер принимает инфу от View и передает свою реакцию в Controller, которая заходит в модель.
_SKif Уровень 41
4 сентября 2021
Вот здесь еще больше деталей: Охота на мифический MVC
Дмитрий Уровень 19
19 июля 2021
А мне показалось очень невнятным объяснение Причем тут фасад и причем тут наблюдатель
Михаил Уровень 37
29 мая 2021
Вот такое MVC логично и обоснованно. Бывает другой подход, при котором контроллер является прослойкой между моделью и видом, и тогда непонятно, зачем, собственно, он нужен. Ладно, пойду заварю какао.
trenny Уровень 29
20 мая 2021
ПМСМ, стрелку "Смотрит" всё же логичней развернуть : смотрит -> "думает") -> изменяет -> данные обрабатываются ядром -> результаты обработки отображаются -> смотрит -> и т.д. Поток, тэкскзать ) А так, да, статья отличная.