Последовательность запрос-обработка-ответ — основа, на которую нанизывается все остальное. Фреймворки идут дальше и разделяют приложение на дополнительные слои уже внутри самого процесса обработки запроса. Без такого разделения код быстро превращается в мешанину из запросов к базе данных, формирований HTML и логики обработки данных. Но с помощью MVC можно выполнять операции отдельно друг от друга.
В этом уроке разберем один из ключевых архитектурных паттернов построения пользовательских приложений — MVC. Мы узнаем, на какие три компонента он разделяется и для чего применяется.
Что такое MVC
Из обработки запроса естественным образом по порядку выделяются следующие слои шаблонов:
- Model — модель
- View — представление
- Controller — контроллер
Остальное добавляется по мере роста сложности приложения. В итоге из этих трех слоев мы и получаем аббревиатуру MVC (Model-View-Controller) — архитектурный паттерн построения пользовательских приложений.
Существует две версии MVC. Первую придумали изначально в сообществе программистов на SmallTalk. Она создавалась под толстые клиенты, а они представляют собой событийные системы, как современные фронтенд-приложения.
На сервере используется другая вариация MVC, которая называется MVC v2. Буквы в ней те же, но означают местами другое. И самое главное, что совсем по-другому строится взаимодействие:
Архитектурный шаблон MVC задает основную структуру приложения и позволяет коду достаточно долго развиваться. При этом он остается удобным в поддержке. MVC с некоторыми модификациями реализуется всеми веб-фреймворками.
Model
Во всех остальных ситуациях выделяют еще один слой, который называют моделью. Она не включает в себя персистентность — постоянное хранение базы данных. Среди разработчиков распространено заблуждение, что модель — это база данных и данные внутри нее. Но это не так.
Слой модели отвечает за бизнес-логику приложения и данные, которые с ней связаны. Технически этот слой может быть представлен большим количеством разных способов, которые зависят от конкретного языка программирования и используемых библиотек. Самый распространенный вариант — это ORM. Но так бывает не всегда. Часто даже при наличии отдельного слоя модели часть логики все же проникает в контроллеры.
Чтобы понять, зачем понадобилось выделять слой модели, прочитайте статью Rails is not your application.
Если кратко, идея заключалась в том, что предметная область, которую мы реализуем внутри нашего сайта, не связана ни с сайтом, ни с фреймворком, используемым внутри. Например, правила бухгалтерии не могут поменяться в зависимости от выбранного фреймворка. Бухгалтерия и фреймворк не связаны. Бизнес-правила этой области не зависят от существования программирования.
С помощью программирования мы можем их выразить в коде, но этот код снова не будет связан с используемым фреймворком. В идеале код, который описывает предметную область и позволяет с ней работать, можно взять и перенести в другой фреймворк без модификаций.
Как видно, на логическом уровне есть граница между кодом, который моделирует предметную область и обслуживает веб-запросы. Но эту границу иногда трудно провести.
Например, сложно сразу определить, к чему относится отправка письма при регистрации, авторизации или восстановлении пароля. Если смотреть еще глубже, то возникают понятия Application Logic и Business Logic, а затем и Service Layer. Если вам интересно, то прочитайте про них самостоятельно.
Самая большая сложность в коде находится именно в этой части приложения. У модели нет четкой структуры, это не классическое запрос-обработка-ответ. Моделирование предметной области — это довольно сложная тема.
Взаимоотношения между слоями в MVC не менее важны, чем их наличие. Модель живет своей жизнью и не знает про существование контроллера или представления. Последние используют модель для запуска бизнес-логики или для формирования HTTP-ответа.
Контроллер инициирует различные процессы и запуск бизнес-логики. Еще он отвечает за формирование ответа и запускает рендеринг шаблонов. Шаблоны не знают про существование слоя контроллера, но используют данные, которые предоставлены им, чтобы формировать, например, HTML или JSON.
View
View или представление — это HTML-шаблон, который возвращает сервер после обработки запроса. Если запрос обрабатывается корректно, мы получим веб-страницу. Если запрос некорректный, мы попадем на страницу ошибки 404.
У шаблонов также есть свой язык, как Jinja2, который позволяет использовать циклы, условия, обрабатывать данные в шаблоне. Несмотря на широкие возможности языка шаблонов, не надо ими злоупотреблять, например, делать вызовы внешних функций или сложные преобразования данных. Все вычисления в модели MVC принято делать на стороне контроллеров, тогда как представление должно уже получать сформированные данные.
Еще одна частая ошибка - формирование отображения данных в контроллере, а не на стороне представления. Словом, если вывод требует, например, обрезать строку до 100 символов, то за эту логику отвечает именно слой представления.
Controller
Под контроллерами понимаются обработчики запросов. Они принимают объект запроса и возвращают объект ответа. В случае Flask, контроллеры представлены функциями, но это не обязательно. В больших фреймворках контроллер — это класс, а обработчики — его методы. Эти методы обычно называют действиями — actions. При таком подходе вся логика сосредоточена в самих контроллерах, что вполне допустимо в самых примитивных случаях.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.