Что такое MVC: рассказываем простыми словами
Современные сайты интерактивные и динамичные, то есть они реагируют на действия пользователя, обрабатывают его запросы и выдают результат. Так работают онлайн-сервисы, например, интернет-банкинг или онлайн-кинотеатр. Для создания интерактивных и динамичных сайтов обычно используется архитектурный паттерн MVC. В этой статье простыми словами объясняется суть этой модели.
- Что такое модель MVC: теория
- Разбираем MVC на примере магазина сэндвичей
- Паттерн MVC в реальной веб-разработке: простые примеры
- Контроллер
- Модель
- Представление
- Заключение
Что такое модель MVC: теория
Статическая страница на HTML не умеет реагировать на действия пользователя. Для двухстороннего взаимодействия нужны динамические веб-страницы. MVC — ключ к пониманию разработки динамических веб-приложений, поэтому разработчику нужно знать эту модель.
MVC расшифровывается как модель-представление-контроллер (от англ.
- Модель — этот компонент отвечает за данные, а также определяет структуру приложения. Например, если вы создаете To-Do приложение, код компонента model будет определять список задач и отдельные задачи.
- Представление — этот компонент отвечает за взаимодействие с пользователем. То есть код компонента view определяет внешний вид приложения и способы его использования.
- Контроллер — этот компонент отвечает за связь между model и view. Код компонента controller определяет, как сайт реагирует на действия пользователя. По сути, это мозг MVC-приложения.
Чтобы лучше понять теоретическую информацию, используем абстрактное описание.
Разбираем MVC на примере магазина сэндвичей
Мы уже рассматривали работу с вложенными коллбэками на примере приготовления гамбургеров. Продолжаем традицию: разберем паттерн MVC на примере магазина сэндвичей.
Представьте, что вы пришли в магазин или кафе, где можно заказать сэндвич. В меню есть бутерброды с тунцом, индейкой и ветчиной. Вы заказываете сэндвич с индейкой.
Продавец или бармен с полуслова понимает вас. Он поворачивается в сторону кухни и говорит поварам, чтобы они приготовили сэндвич с индейкой.
У поваров под рукой есть разные продукты: тунец, индейка, ветчина, сыр, листья салата и другие ингредиенты, которые добавляют в бутерброды. Они выбирают только то, что нужно для вашего сэндвича с индейкой. Вы получаете свой заказ.
Покупку бутерброда можно описать через MVC:
- Модель: кухня, на которой повар делает сэндвич.
- Представление: готовый бутерброд, который вы с удовольствием едите.
- Контроллер: продавец или бармен, который принимает заказ и передаёт его на кухню.
Вы уже представляли готовый сэндвич с индейкой, когда заказывали его бармену.
Справка: иногда модель MVC расшифровывают как модель-вид-контроллер. Это не ошибка, но всё-таки корректнее переводить view как представление.
Точно так же можно представить взаимодействие с сайтом. Когда вы заходите в «Фейсбук» и переходите по ссылке «Друзья», то заранее представляете результат перехода по ссылке. Это список ваших друзей.
Когда вы нажимаете на ссылку «Друзья», на сервер «Фейсбука» уходит запрос. В нём содержится просьба показать вам список друзей. Это очень похоже на просьбу продать вам бутерброд с индейкой. Это контроллер.
На сервере «Фейсбука» ваш запрос обрабатывается. Программа достаёт из базы данных всех ваших друзей, чтобы показать список. Это можно сравнить с кухней и поварами из примера с сэндвичем. Это модель.
«Фейсбук» берёт нужные ингредиенты из базы данных и готовит ваш заказ: список друзей. Тем же занимались повара на кухне магазина сэндвичей. Это снова представление или view.
Промежуточный итог:
- Бармен — это контроллер. Он знает все варианты сэндвичей из меню и может передать ваш заказ на кухню.
- Повара на кухне — это модель. Они знают, какие взять ингредиенты и что с ними сделать, чтобы выполнить конкретный заказ.
- Сэндвич — это представление. Речь об итоговом продукте, который пользователь сначала заказывает, а потом получает.
Изучайте фронтенд- и бэкенд-разработку на JavaScript На Хекслете есть профессии «Фронтенд-программист» и «Node.js-программист». В процессе обучения на этих профессиях вы научитесь программировать на JavaScript, изучите современные инструменты для разработки фронтенд- и бэкенд-приложений, включая React, Redux, Express.js, Koa, PostgreSQL. Первые курсы в профессиях доступны бесплатно.
Паттерн MVC в реальной веб-разработке: простые примеры
Ниже представлены простые примеры MVC, которые используются в веб-фреймворках.
Контроллер
Контроллер обрабатывает входящие запросы. В фреймворке это может заключаться в определении конкретных URL, на которые попадает пользователь при переходе по ссылке или при нажатии кнопки.
Переход по ссылке website(.)com/profile/ -> возвращает profilewebsite(.)com/friends/ -> возвращает friendswebsite(.)com/friend={userName}/ -> возвращает профиль конкретного друга
Модель
Модель отвечает за данные, которые хранятся и обрабатываются на сервере.
User: { userName: { firstName, lastName }, friends }
Представление
Это HTML-шаблон, который возвращает сервер после обработки запроса. Если запрос корректно обрабатывается, вы получаете веб-страницу со списком друзей. Если запрос некорректный, вы попадаете на страницу ошибки 404.
<ul> <li>Friend 1: {friendList[0].userName}</li> <li>Friend 2: {friendList[1].userName}</li> <li>Friend 3: {friendList[2].userName}</li> . .. </ul>
Заключение
MVC — подход к проектированию приложения, который предполагает выделение кода в блоки модель, представление и контроллер. Контроллер обрабатывает входящие запросы. Модель достаёт из базы данных информацию, нужную для выполнения конкретных запросов. Представление определяет результат запроса, который получает пользователь.
Если у вас остались вопросы по MVC, задавайте их в комментариях.
Это адаптированный перевод статьи What is MVC, and how is it like a sandwich shop?
Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях
Шаблон проектирования (программирования) MVC.
Одно из понятий, с которым приходится часто встречаться в программировании — это понятие шаблона программирования или проектирования MVC.
MVC — это всего лишь один способов, как вы можете организовать свой код. Он описывает некоторые правила, как это нужно делать.
Нужно понимать, что это не единственный способ организации кода. Существуют и другие способы.
Задача MVC — сделать так, чтобы наш код проще воспринимался, проще читался и проще и быстрее обрабатывался компьютером.
Основная идея MVC — разделить внешний вид приложения от логики. Т.к. мы говорим о веб-приложениях, то под внешним видом у нас понимается HTML-разметка документа и его CSS оформление. А под логикой мы понимаем различные скрипты, функции, классы и.т.д.
Шаблон MVC — это аббревиатура, которая состоит из первых букв тех составляющих, которые в нее входят: Модель и Контроллер (скрипты и логика) и Вид (HTML и CSS (шаблонизатор)),.
В логике не должно быть внешнего вида, а во внешнем виде не должно быть логики. Здесь важно понимать такой момент: не то, чтобы вы не можете нарушить это правило, вы это сделать можете и ваша программа будет работать. Идея в то, что разместив код таким образом, вы отклоняетесь от модели MVC и теряете все преимущества, которые эта модель предоставляет.
Модель MVC — это всего лишь набор рекомендаций, которым нужно придерживаться при написании кода. Эти рекомендации даны вам для вашего же блага, чтобы в дальнейшем вы потом легче читали код, легче его анализировали и.т.д.
В модели MVC самым главным элементом, с которого все начинается и на котором все, как правило, заканчивается — это контроллер.
Задача контроллера — принять запрос пользователя и решить, что делать с этим запросом далее, если требуется, то перенаправить запрос в модель, который обработает информацию и возвращает ее контроллеру.
После того, как информация обработана, контроллер решает, что с ней делать дальше, если пользователю достаточно предоставить просто набор каких-то данных, не в виде html-странице, а например, в формате json, контроллер этот набор данных ему выдает.
Если необходимо сформировать html-страницу, контроллер передает эти данные в вид и внутри вида шаблонизатор формирует каркас страницы, выдает ее назад контроллеру и контроллер уже выдает этот каркас пользователю в виде html-страницы.
Из 3 частей MVC модели контроллер является обязательной частью. Остальные части являются опциональными. Если пользователю достаточно только отдать какой-то набор данных, то можно обойтись без вида. Если не нужно обрабатывать данные, то можно обойтись без модели.
Контроллер — это некоторая функция. Может содержать ссылки на какие-то другие функции и возвращает какой-то результат.
Контроллер можно сравнить с начальником отдела на предприятии. Начальнику отдела приходит задание от директора предоставить какой-то отчет и далее контроллер, под которым мы имеем в виду начальника отдела, принимает решение. Или он сам сделает этот отчет и отдаст его директору или он может передать ее выполнение своим подчиненным. В качестве подчиненного можно представить «модель».
Модель — это «подчиненный», который делает какую-то рутинную работу, выполняет обработку данных. Он произвел эту обработку данных и выдал результат начальнику (контроллеру). Контроллер принял этот отчет.
После того, как данные обработаны, начальник (контроллер) относит этот отчет директору (т.е. человеку, который запросил эти данные).
Примерно на таком же принципе работает и модель MVC.
Вид — можно представить тоже в виде каких-то работников отдела, которые набирают уже подготовленные данные от модели на компьютере, например в текстовом редакторе Microsoft Word и распечатывают его. Вот, по сути, этом и заключается задача «вида».
Задача модели — это такие работники, которые производят расчеты, расчетчики какие-то и.т.д. Примерно такую аналогию можно произвести.
Модель — это работник или исполнитель. Содержит основные функции и классы (логику).
Не всегда удается и целесообразно придерживаться структуры Controller — Model. В принципе, можно какую-то программную логику и более целесообразно, если этой логики мало, написать эту логику внутри контроллера. Нет необходимости создавать дополнительные функции и отдельные классы, чтобы сделать всего несколько действий.
Самое главное, что я хотел донести — модель MVC — это всего лишь рекомендация. По структурированию и формированию кода. Придерживаться ее или нет, решать, конечно, вам. Самое главное понять идею для чего это нужно, а далее вы сами, по ходу работы вы можете определять, нужно ли вам придерживаться этой модели или нет.
Курс JSP & Servlets — Лекция: Подход MVC
Знакомство с архитектурой MVC
Самая популярная архитектура приложений, о которой знает каждый программист, — это MVC. MVC расшифровывается как Model-View-Controller.
Это не столько архитектура приложений, как архитектура компонентов приложения, но к этому нюансу вернемся попозже.
MVC — это схема разделения данных приложения и управляющей логики на три отдельных компонента: модель, представление и контроллер — таким образом, что модификация каждого компонента может осуществляться независимо.
- Модель (Model) предоставляет данные и реагирует на команды контроллера, изменяя свое состояние.
- Представление (View) отвечает за отображение данных модели пользователю, реагируя на изменения модели.
- Контроллер (Controller) интерпретирует действия пользователя, оповещая модель о необходимости изменений.
Эту модель придумали еще в 1978 (!) году. Да, проблемы с правильной архитектурой ПО были актуальны еще 50 лет назад. Вот как эта модель описывается диаграммой в оригинале:
Модель предоставляет данные и методы работы с ними: запросы в базу данных, проверку на корректность. Модель не зависит от представления (не знает как данные визуализировать) и контроллера (не имеет точек взаимодействия с пользователем), предоставляя доступ к данным и управлению ими.
Модель строится таким образом, чтобы отвечать на запросы, изменяя свое состояние, при этом может быть встроено уведомление “наблюдателей”. Модель, за счет независимости от визуального представления, может иметь несколько различных представлений для одной “модели”.
Представление отвечает за получение необходимых данных из модели и отправляет их пользователю. Представление не обрабатывает введенные данные пользователя.
Контроллер обеспечивает “связь” между пользователем и системой. Контролирует и направляет данные от пользователя к системе и наоборот. Использует модель и представление для реализации необходимого действия.
Определенная сложность есть с тем, что данная модель за десятки лет немного эволюционировала. То есть название осталось тем же, а назначение частей начало меняться.
Архитектура MVC в вебе
Идея, которая лежит в основе конструкционного шаблона MVC, очень проста: нужно четко разделять ответственность за различное функционирование в наших приложениях:
Model — обработка данных и логика приложения.
View — предоставления данных пользователю в любом поддерживаемом формате.
Controller — обработка запросов пользователя и вызов соответствующих ресурсов.
Приложение разделяется на три основных компонента, каждый из которых отвечает за различные задачи. Давай подробно разберем компоненты клиент-серверного приложения на примере.
Контроллер (Controller)
Пользователь кликает на различные элементы на странице в браузере, в результате чего браузер отправляет различные HTTP запросы: GET, POST или другие. К контроллеру можно отнести браузер и JS-код, которые работают внутри страницы.
Основная функция контроллера в данном случае — это вызывать методы у нужных объектов, управлять доступом к ресурсам для выполнения задач, заданных пользователем. Обычно контроллер вызывает соответствующую модель для задачи и выбирает подходящий вид.
Модель (Model)
Модель в широком смысле — это данные и правила, которые используются для работы с данными — вместе они составляют бизнес-логику приложения. Проектирование приложения всегда начинается с построения моделей объектов, которыми оно оперирует.
Допустим, у нас есть интернет-магазин, который торгует книгами, тогда человек — это только пользователь приложения или еще и автор книги? Эти важные вопросы должны быть решены во время проектирования модели.
Дальше идут наборы правил: что можно делать, что нельзя, какие наборы данных допустимы, а какие нет. Может ли книга быть без автора? А автор без книг? Может ли дата рождения пользователя быть в 300 году и тому подобное.
Модель дает контроллеру представление данных, которые запросил пользователь (сообщение, страницу книги, картинки, и тому подобное). Модель данных будет одинаковой, вне зависимости от того, как мы хотим представлять их пользователю. Поэтому мы выбираем любой доступный вид для отображения данных.
Модель содержит наиболее важную часть логики нашего приложения, логику, которая решает задачу, с которой мы имеем дело (форум, магазин, банк и тому подобное). Контроллер содержит в основном организационную логику для самого приложения (прямо как твой Project Manager).
Вид (View)
View обеспечивает различные способы представления данных, которые получены из модели. Он может быть шаблоном, который заполняется данными. Может быть несколько различных views и контроллер выбирает, какой подходит наилучшим образом для текущей ситуации.
Веб-приложение обычно состоит из набора контроллеров, моделей и видов (views). Контроллер может быть только на бэкенде, но также может быть вариант нескольких контроллеров, когда его логика размазывается и по frontend’у тоже. Хороший пример такого подхода — любое мобильное приложение.
Пример MVC в вебе
Допустим тебе нужно разработать интернет-магазин, который будет заниматься продажей книг. Пользователь может выполнять следующие действия: просматривать книги, регистрироваться, покупать, добавлять пункты к текущему заказу, отмечать понравившиеся книги и покупать их.
В твоем приложении должна быть модель, которая отвечает за всю бизнес-логику. Также нужен контроллер, который будет обрабатывать все действия пользователей и превращать их в вызовы методов из бизнес-логики. При этом один метод контроллера может вызвать много различных методов модели.
Также тебе нужны наборы views: список книг, информация об одной книге, корзина, список заказов. Каждая страница веб-приложения — это фактически и есть отдельный view, который отображает пользователю определенный аспект модели.
Давай посмотрим, что произойдет, если пользователь откроет список рекомендованных магазином книг для просмотра названий. Всю последовательность действий можно описать в виде 6 шагов:
Шаги:
- Пользователь кликает по ссылке «рекомендованы» и браузер отправляет запрос на, допустим, /books/recommendations.
- Контроллер проверяет запрос: пользователь должен быть залогинен. Или у нас должны быть подборки книг для незалогиненных пользователей. Затем контроллер обращается к модели и просит ее отдать список книг, рекомендованных пользователю N.
- Модель обращается в базу данных, достает оттуда информацию о книгах: популярные сейчас книги, книги, купленные пользователем, книги, купленные его друзьями, книги из его wish list. На основе этих данных модель строит список из 10 рекомендованных книг и возвращает их контроллеру.
- Контроллер получает список рекомендованных книг и смотрит на него. На этом этапе контроллер принимает решения! Если книг мало или список вообще пустой, то он запрашивает список книг для незалогиненного пользователя. Если сейчас идет акция, то контроллер может добавить в список акционные книги.
- Контроллер определяется с тем, какую страницу показать пользователю. Это может быть страница с ошибкой, страница со списком книг, страница поздравление о том, что пользователь стал миллионным посетителем.
- Сервер отдает клиенту страницу (view), выбранную контроллером. Она заполняется нужными данными (имя пользователя, список книг) и уходит к клиенту.
- Клиент получает страницу и отображает ее пользователю.
В чем преимущества такого подхода?
Самое очевидное преимущество, которое мы получаем от использования концепции MVC — это четкое разделение логики представления (интерфейса пользователя) и логики приложения (серверная часть).
Второе преимущество — это разделение серверной части на две: умная модель (исполнитель) и контроллер (центр принятия решений).
В предыдущем примере был момент, когда контроллер мог получить от модели пустой список рекомендованных книг и решал, что ему с ним делать. Теоретически эту логику можно было бы засунуть сразу в модель.
Сначала при запросе рекомендованных книг модель бы решала, что делать, если список пустой. Затем пришлось бы в это же место добавить код, что делать, если сейчас идет акция, затем еще разные варианты.
Потом оказалось, что админ магазина хочет посмотреть, как будет выглядеть страница пользователя без акции, или наоборот сейчас акции нет, а он хочет посмотреть, как будет отображаться будущая акция. А методов-то для этого нет. Поэтому и было решено отделить центр принятия решений (контроллер) от бизнес-логики (модель).
Помимо изолирования видов от логики приложения, концепция MVC существенно уменьшает сложность больших приложений. Код получается гораздо более структурированным, и, тем самым, облегчается поддержка, тестирование и повторное использование решений.
Понимая концепцию MVC, ты как разработчик осознаешь, где нужно добавить сортировку списка книг:
- На уровне запроса к базе данных.
- На уровне бизнес-логики (модели).
- На уровне бизнес-логики (контроллер).
- В представлении — на стороне клиента.
И это не риторический вопрос. Вот прямо сейчас и подумай: где и почему нужно добавить код по сортировке списка книг.
Классическая модель MVC
Взаимодействие между компонентами MVC реализуется по-разному в веб-приложениях и в мобильных приложениях. Это происходит из-за того, что веб-приложение — короткоживущее, обрабатывает один запрос пользователя и завершается, а мобильное приложение обрабатывает много запросов без перезапуска.
В веб-приложениях обычно используется «пассивная» модель, а в мобильных приложениях — «активная». Активная модель, в отличие от пассивной, позволяет подписываться и получать уведомления об изменении в ней. В случае с веб-приложениями этого не требуется.
Примерно вот так выглядит взаимодействие компонентов в различных моделях:
В мобильных приложениях (активная модель) активно используются события и механизм подписки на события. При таком подходе view (вид) подписывается на изменения модели. Затем, когда происходит какое-то событие (например, пользователь нажимает кнопку), вызывается контроллер. Он дает и модели команду на изменение данных.
Если какие-то данные изменились, то модель генерирует событие об изменении этих данных. Все view, которые подписались на это событие (для которых важно изменение именно этих данных), получают это событие и обновляют данные в своем интерфейсе.
В веб-приложениях все организовано немного по-другому. Основное техническое отличие — это то, что клиент не может получать сообщения со стороны сервера по инициативе сервера.
Поэтому контроллер в веб-приложении обычно не присылает view какие-либо сообщения, а отдает клиенту новую страницу, которая технически является новым view или даже новым клиентским приложением (если одна страница ничего не знает о другой).
В нынешнее время эта проблема частично решена с помощью таких подходов:
- Регулярный опрос сервера на счет изменения важных данных (раз в минуту или чаще).
- WebSocket’ы позволяют клиентку подписываться на сообщения сервера.
- Web-push-уведомления со стороны сервера.
- Протокол HTTP/2 позволяет серверу инициировать отправку сообщений клиенту.
Разделение кода — Основы Веб-программирования
Каналы передачи данных | Сетевое программирование | Базы данных | Основы Веб-программирования
См.также
- Сравнение скорости фреймворков и чистого WSGI
В программном обеспечении принято разделять: программную логику, код, который относится к данным, настройки и шаблоны. Таким образом, код становится более структурированным, и его легче развивать, а также сопровождать в дальнейшем.
MVC
См.также
- Статья о фреймворке Ruby on Rails
- Концепция MVC для чайников
MVC (Model-View-Controller: модель-вид-контроллер) — шаблон архитектуры ПО, который подразумевает разделение программы на 3 слабосвязанных компонента, каждый из которых отвечает за свою сферу деятельности.
Бешеная популярность данной структуры в Веб-приложениях сложилась благодаря её включению в две среды разработки, которые стали очень востребованными: Struts и Ruby on Rails. Эти среды разработки наметили пути развития для сотен рабочих сред, созданных позже.
Паттерн MVC (Model-View-Controller)
- Model — модель, предоставляющая доступ к данным. Позволяет извлекать данные и менять их состояние;
- View — представление, отображающее данные клиенту. В веб-программировании существует в виде конечных данных (HTML, JSON, …), которые получает клиент. Может формироваться при помощи генераторов по заданному шаблону, например Jinja2, Mako; или систем для построения интерфейсов по разметке, таких, как Windows Presentation Foundation (WPF), либо Qt Widgets; или описываться декларативно, как это делается в QML и ReactJs.
- Controller — контроллер, отслеживающий различные события (действия пользователя) и по заданной логике оповещающий модель о необходимости изменить состояние системы.
Классические MVC фреймворки:
- Ruby on Rails
- Pylons
MTV
Фреймворк Django ввел новую терминологию MTV.
Примечание
https://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names
В Django функции, отвечающие за обработку логики, соответствуют части Controller из MVC, но называются View, а отображение соответствует части View из MVC, но называется Template. Получилось, что:
- M -> M Модели остались неизменными
- V -> T Представление назвали Templates
- C -> V Контроллеры назвали Views
Так появилась аббревиатура MTV.
TADA!! Django invented MTV
Вся логика при таком подходе вынесена во View, а то, как будут отображаться данные в Template. Из-за ограничений HTTP протокола, View в Django описывает, какие данные будут представленны по запросу на определенный URL. View, как и протокол HTTP, не хранит состояний и по факту является обычной функцией обратного вызова, которая запускается вновь при каждом запросе по URL. Шаблоны (Templates), в свою очередь, описывают, как данные представить пользователю.
Паттерн MTV (Model-Template-View)
MTV фреймворки:
- Django
RV
См. также
- RV Pyramid
- Что не так в терминологии MVC
- Pyramid wikipedia
В защиту своего дизайна авторы Pyramid написали довольно большой документ, который призван развеять мифы о фреймворке. Например, на критику модели MVC в Pyramid следует подробное объяснение, что MVC «притянут за уши» к веб-приложениям. Следующая цитата хорошо характеризует подход к терминологии в Pyramid:
«Мы считаем, что есть только две вещи: ресурсы (Resource) и виды (View). Дерево ресурсов представляет структуру сайта, а вид представляет ресурс.
«Шаблоны» (Template) в реальности лишь деталь реализации некоторого вида: строго говоря, они не обязательны, и вид может вернуть ответ (Response) и без них.
Нет никакого «контроллера» (Controller): его просто не существует.
«Модель» (Model) же либо представлена деревом ресурсов, либо «доменной моделью» (domain model) (например, моделью SQLAlchemy), которая вообще не является частью каркаса.
Нам кажется, что наша терминология более разумна при существующих ограничениях веб-технологий.»
Паттерн RV (Resources-View)
Веб ограничен URL, который и представляет из себя дерево ресурсов или структуру сайта.
Также протокол HTTP не позволяет хранить состояние и отправлять/принимать оповещения клиенту от сервера, что ограничивает возможность отслеживания действий клиента для последующего уведомления модели на изменение состояния.
Поэтому данные часто используются на «frontend»-е (например в связке React/Redux), а на стороне сервера формируются только один раз во время ответа, либо загружаются отдельным запросом при помощи AJAX, или даже с помощью других протоколов, например WebSocket.
RV фреймворки:
- Pyramid
Пример MVC блога
Структура файлов
Приведем структуру нашего блога к следующему виду:
. ├── __init__.py ├── models.py └── views. py 0 directories, 3 files
Примечание
Исходный код доступен по адресу:
- https://github.com/iitwebdev/lectures_wsgi_example/tree/master/1.mvc
Где:
__init__.py
— входная точка программы, которая содержит основные настройки и запуск Веб-сервераmodels.py
— код, который представляет данные, обычно называется моделиviews.py
— логика программы (в нашем случае WSGI-приложения)
Предупреждение
Примеры работают только в Python3
Данные
models.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ARTICLES = [ { 'id': 1, 'title': 'Lorem ipsum dolor sid amet!', 'content': ''' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vel tortor eleifend, sollicitudin nisl quis, lacinia augue. Duis quam est, laoreet sit amet justo vitae, viverra egestas sem. Maecenas pellentesque augue in nibh feugiat tincidunt. Nunc magna ante, mollis vitae ultricies eu, consectetur id ante. In ut libero eleifend, blandit ipsum a, ullamcorper nunc. Sed bibendum eget odio eget pellentesque. Curabitur elit felis, pellentesque id feugiat et, tincidunt ut mauris. Integer vitae vehicula nunc. Integer ullamcorper, nunc in volutpat auctor, elit leo convallis nulla, vitae varius mi nisl ac lorem. Sed a lacus mi. In hac habitasse platea dictumst. Cras in posuere velit, id dignissim nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla bibendum suscipit convallis. ''' }, { 'id': 2, 'title': 'Hello', 'content': 'Test2' }, { 'id': 3, 'title': 'World', 'content': 'Test2' }, ] |
Авторизация
Мы использовали самописные WSGI-middleware, которые решают стандартные задачи. Заменим их на уже существующие:
- selector — URL-диспетчеризация
- wsgi-basic-auth — авторизация по методу Basic Auth
Настройки авторизации __init__. py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from views import BlogRead, BlogIndex, BlogCreate, BlogDelete, BlogUpdate from wsgi_basic_auth import BasicAuth # third-party import selector def make_wsgi_app(): passwd = { 'admin': '123' } # BasicAuth applications create = BasicAuth(BlogCreate, 'www', passwd) update = BasicAuth(BlogUpdate, 'www', passwd) delete = BasicAuth(BlogDelete, 'www', passwd) # URL dispatching middleware dispatch = selector.Selector() dispatch.add('/', GET=BlogIndex) dispatch.prefix = '/article' dispatch.add('/add', GET=create, POST=create) dispatch.add('/{id:digits}', GET=BlogRead) dispatch.add('/{id:digits}/edit', GET=update, POST=update) dispatch.add('/{id:digits}/delete', GET=delete) return dispatch if __name__ == '__main__': from paste.httpserver import serve app = make_wsgi_app() serve(app, host='0. 0.0.0', port=8000) |
URL-диспетчеризация
Настройки URL-диспетчеризации __init__.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from views import BlogRead, BlogIndex, BlogCreate, BlogDelete, BlogUpdate from wsgi_basic_auth import BasicAuth # third-party import selector def make_wsgi_app(): passwd = { 'admin': '123' } # BasicAuth applications create = BasicAuth(BlogCreate, 'www', passwd) update = BasicAuth(BlogUpdate, 'www', passwd) delete = BasicAuth(BlogDelete, 'www', passwd) # URL dispatching middleware dispatch = selector.Selector() dispatch.add('/', GET=BlogIndex) dispatch.prefix = '/article' dispatch.add('/add', GET=create, POST=create) dispatch.add('/{id:digits}', GET=BlogRead) dispatch.add('/{id:digits}/edit', GET=update, POST=update) dispatch.add('/{id:digits}/delete', GET=delete) return dispatch if __name__ == '__main__': from paste. httpserver import serve app = make_wsgi_app() serve(app, host='0.0.0.0', port=8000) |
WSGI-приложение можно указывать как объект (BlogRead
) или как строку
импорта ("views.BlogIndex"
).
views.py
:
1 2 3 4 5 6 7 8 9 | class BaseArticle(BaseBlog): def __init__(self, *args): super(BaseArticle, self).__init__(*args) article_id = self.environ['wsgiorg.routing_args'][1]['id'] (self.index, self.article) = next(((i, art) for i, art in enumerate(ARTICLES) if art['id'] == int(article_id)), (None, None)) |
urlrelay добавляет результат поиска в переменную с названием wsgiorg.routing_args
.
WSGI-приложения
Практически не изменились.
views.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | from models import ARTICLES class BaseBlog(object): def __init__(self, environ, start_response): self. environ = environ self.start = start_response class BaseArticle(BaseBlog): def __init__(self, *args): super(BaseArticle, self).__init__(*args) article_id = self.environ['wsgiorg.routing_args'][1]['id'] (self.index, self.article) = next(((i, art) for i, art in enumerate(ARTICLES) if art['id'] == int(article_id)), (None, None)) class BlogIndex(BaseBlog): def __iter__(self): self.start('200 OK', [('Content-Type', 'text/html')]) yield b'<h2>Simple Blog</h2>' yield b'<a href="/article/add">Add article</a>' yield b'<br />' yield b'<br />' for article in ARTICLES: yield str.encode( ''' {0} - (<a href="/article/{0}/delete">delete</a> | <a href="/article/{0}/edit">edit</a>) <a href="/article/{0}">{1}</a><br /> '''. format( article['id'], article['title'] ) ) class BlogCreate(BaseBlog): def __iter__(self): if self.environ['REQUEST_METHOD'].upper() == 'POST': from urllib.parse import parse_qs values = parse_qs(self.environ['wsgi.input'].read()) max_id = max([art['id'] for art in ARTICLES]) ARTICLES.append( {'id': max_id+1, 'title': values[b'title'].pop().decode(), 'content': values[b'content'].pop().decode() } ) self.start('302 Found', [('Content-Type', 'text/html'), ('Location', '/')]) return self.start('200 OK', [('Content-Type', 'text/html')]) yield b'<h2><a href="/">Simple Blog</a> -> CREATE</h2>' yield b''' <form action="" method="POST"> Title:<br> <input type="text" name="title"><br> Content:<br> <textarea name="content"></textarea><br><br> <input type="submit" value="Submit"> </form> ''' class BlogRead(BaseArticle): def __iter__(self): if not self. article: self.start('404 Not Found', [('content-type', 'text/plain')]) yield b'not found' return self.start('200 OK', [('Content-Type', 'text/html')]) yield b'<h2><a href="/">Simple Blog</a> -> READ</h2>' yield str.encode( '<h3>{}</h3>'.format(self.article['title']) ) yield str.encode(self.article['content']) class BlogUpdate(BaseArticle): def __iter__(self): if self.environ['REQUEST_METHOD'].upper() == 'POST': from urllib.parse import parse_qs values = parse_qs(self.environ['wsgi.input'].read()) self.article['title'] = values[b'title'].pop().decode() self.article['content'] = values[b'content'].pop().decode() self.start('302 Found', [('Content-Type', 'text/html'), ('Location', '/')]) return self.start('200 OK', [('Content-Type', 'text/html')]) yield b'<h2><a href="/">Simple Blog</a> -> UPDATE</h2>' yield str. encode( ''' <form action="" method="POST"> Title:<br> <input type="text" name="title" value="{0}"><br> Content:<br> <textarea name="content">{1}</textarea><br><br> <input type="submit" value="Submit"> </form> '''.format( self.article['title'], self.article['content'] ) ) class BlogDelete(BaseArticle): def __iter__(self): self.start('302 Found', # '301 Moved Permanently', [('Content-Type', 'text/html'), ('Location', '/')]) ARTICLES.pop(self.index) yield b'' |
Как работает архитектурный паттерн “модель-вид-контроллер” | by Рудольф Коршун
За последние двадцать лет веб-сайты превратились из простых страниц с вкраплением CSS в гораздо более сложные и мощные приложения.
Чтобы упростить разработку этих приложений, программисты пользуются различными шаблонами и программными архитектурами, которые упрощают код.
Но для начала: что такое архитектура программного обеспечения?
Архитектура — это системный подход к описанию программного обеспечения. Это касается в том числе отношения ПО с другими программами и к того, как эти программы взаимодействуют друг с другом.
Архитектура программного обеспечения включает и другие факторы, такие как бизнес-стратегию, атрибуты качества, динамику человеческих ресурсов, дизайн и IT-среду.
Иными словами, архитектура служит чертежом системы.
Самая популярная архитектура ПО на сегодняшний день — “модель-вид-контроллер”, или сокращенно MVC.
MVC делит любое крупное приложение на три части:
- Модель.
- Вид (или, по-другому, представление).
- Контроллер.
Каждый из этих компонентов предназначен для обработки определенного аспекта приложения и служит различной цели.
Модель
Модель содержит всю логику данных, с которой работает пользователь: схемы и интерфейсы проекта, базы данных и их поля.
Например, объект клиента будет извлекать информацию о клиенте из базы данных, манипулировать записями в БД и обновлять их или пользоваться полученной информацией для визуализации данных.
Вид
Вид содержит пользовательский интерфейс и представление приложения.
Например, представление клиента будет включать все компоненты пользовательского интерфейса: текстовые поля, раскрывающиеся списки и другие элементы, с которыми взаимодействует пользователь.
Контроллер
И, наконец, контроллер содержит всю бизнес-логику и обрабатывает входящие запросы. Это интерфейс между моделью и представлением.
Например, контроллер клиента будет обрабатывать все взаимодействия и входные данные из представления клиента и обновлять базу данных с использованием модели клиента. Тот же контроллер будет задействован для просмотра данных о клиентах.
Вот схема, которая поможет визуализировать архитектуру MVC и принцип ее работы:
Блок-схема MVCСначала браузер отправляет запрос Контроллеру. Затем Контроллер взаимодействует с Моделью для отправки и получения данных.
Потом Контроллер взаимодействует с Представлением для визуализации данных. Представление занимается только тем, как представить информацию, а не окончательным отображением. Отображать данные на основе того, что отправляет Контроллер, будет уже динамический HTML-файл.
Наконец, Представление отправит окончательный вид Контроллеру, а Контроллер передаст эти данные на вывод пользователям.
Важно то, что Представление и Модель никогда не взаимодействуют напрямую. Единственное взаимодействие между ними происходит через Контроллер.
Это означает, что логика приложения и интерфейс никогда не пересекаются, что облегчает написание сложных приложений.
Рассмотрим простой пример:
Что здесь происходит? Во-первых, пользователь в веб-браузере или мобильном приложении вводит, что ему нужен список фильмов.
Затем браузер отправляет запрос Контроллеру, чтобы получить этот список фильмов.
Затем Контроллер просит Модель извлечь список фильмов из базы данных.
router.get('/',ensureAuth, async (req,res)=>{
try{
const movies = await Movies.find() (*)
res.render('movies/index',{ movies })
}catch(err){ console.error(err)
res.render('error/500') } })
Здесь Контроллер отправляет запрос для вызова всех членов списка фильмов (по номерам строк).
Затем Модель выполняет поиск в базе данных и возвращает список фильмов Контроллеру.
Вот как это выглядит в виде схемы:
const mongoose = require('mongoose')
const MovieSchema = new mongoose.Schema
({
name:{
type:String,
required:true
},
description:{
type:String
}
})module.exports = mongoose.model('Movies',MovieSchema)
Если Контроллер получит список фильмов от Модели, то попросит Представление отобразить список фильмов.
router.get('/',ensureAuth, async (req,res)=>{
try{ const movies = await Movies.find()
res.render('movies/index', { movies (*) }) }catch(err){
console.error(err) res.render('error/500') }
})
Контроллер здесь отправляет Представлению список фильмов для отображения (по номерам строк).
Представление получит запрос и вернет Контроллеру обработанный список фильмов в формате HTML.
<div>
<div>
<div>
<div>{{movie.title}}</div>
</div> <div>
<a href="/movies/{{movie._id}}"> More from {{movie.description}} </a>
</div>
</div>
</div>
Наконец, Контроллер возьмет этот HTML-код и отправит пользователю, формируя на выходе список фильмов.
Есть множество программных архитектур, но Model-View-Controller — самая популярная и распространенная. Она снижает сложность кода и делает программы понятными.
Теперь вы знаете концепции, лежащие в основе паттерна MVC.
Вот и все, счастливого обучения!
Читайте также:
- Построение бесконечного списка с помощью SwiftUI и Combine
- Что делает сайты медленнее?
- Внутренняя жизнь React Native
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи: Nishant Kumar, “How the Model View Controller Architecture Works — MVC Explained”
Архитектурные шаблоны в ABAP: MVC, MVP, MVVM, MVA
MVC (Model-View-Controller) — фундаментальный шаблон проектирования, целью которого является отделение логики интерфейса пользователя от логики программирования. MVC имеет множество вариантов реализации. Существуют модификации шаблона, самые известные из них MVP и MVVM.
Ниже описана концепция архитектурного шаблона MVC и его модификаций MVP и MVVM. Приведена концепция шаблона MVA, основанная на паттернах MVC, MVP и MVVM и адаптирована под язык ABAP.
Model-View-Controller
- Model (модель) — содержит модель данных и бизнес-логику. Иными словами, модель делает все для чего создавалась программа.
- View (представление) — интерфейс взаимодействия с пользователем. Представление отображает часть данных модели пользователю. В некоторых случаях, представление может иметь свою бизнес-логику.
- Controller (контроллер) — связывает модель и представление между собой. Контроллер обрабатывает события пользователя, управляет состоянием модели.
Точкой входа в программу является контроллер. Контроллер имеет ссылки на модель и на представление. Контроллер подписывается на события представления, а представление подписывается на события модели.
Когда пользователь совершает какие-нибудь действия, управление переходит к контроллеру и контроллер воздействует на модель.
При изменении модели идет воздействие контроллер получает соответствующее событие и воздействует на представление для обновления данных.
В реализации MVC независимой частью является модель, она ничего не знает о представлении и контроллере.
Если программа содержит несколько представлений (например, несколько ABAP-экранов), то для каждого представления требуется создать свой контроллер. При этом, допускается использовать одну и туже модель в разных контроллерах и представлениях.
Реализация MVC в ABAP подробно описана в книге Design Patterns in ABAP Objects с примерами ALV и Web Dynpro представлений.
Model-View-Presenter
Компоненты Model и View в шаблоне MVP аналогичны соответствующим компонентам модели MVC. Основной целью данного шаблона является отделения модели от представления. В шаблоне MVP информация об изменении модели поступает на презентер (Presenter), который воздействует на представление для обновления состояния.
Отсутствие связи между моделью и представлением позволяет сделать абстракцию представления. Реализовать данный паттерн можно путем выделения интерфейса представления IView. Интерфейс будет содержать набор методов и свойств, необходимых презентеру, сам презентер будет подписываться на события представления и вызывать методы для его обновления. Абстрагирование представления полезно в задачах, где требуется отобразить один и тот же набор данных в разных представлениях. Например, выводить отчет в разных форматах: ALV, PDF, EXCEL.
Model-View-ViewModel
Шаблон MVVM предназначен для разработки в WPF на языке C#. Но его идею можно применять и в ABAP. Идея данного паттерна заключается в отделении слов друг от друга. Слой View знает только о ViewModel, ViewModel знает только о Model.
Представление не требует реализации IView, для получения данных ему требуется передать ссылку на источник данных (DataContext). ViewModel является посредником между передачей данных от модели в DataContext, элементы представления ссылаются на источник данных через биндинги (Binding).
Важное отличие MVVM от MVC и MVP то, что представление в MVVM может менять модель напрямую за счет двухстороннего биндинга. В случае с MVC и MVP представление имеет доступ «только на чтение» к данным модели.
Model-View-Application
Особенностью ABAP приложений является то, то представление может обновиться только после действий пользователя. Даже если какой-нибудь асинхронный процесс поменяет модель, то инициировать обновление представление он не сможет. Данная особенность позволяет ослабить связь модель-представление и делегировать функцию обновления представления самому представлению. Иными словами, представление само должно решать, когда надо обновить себя, а когда нет.
Если взять за основу паттерны MVP и MVVM и принять во внимание отсутствие обратной связи от модели до представления, то можно спроектировать новый архитектурный шаблон MVA.
Концепция MVA
Реализация MVA основана на объектно-ориентированном подходе, где на каждый слой архитектуры будет реализован один или несколько классов. Каждый из слоев обладает рядом свойств.
Представление (View и IView):
- MVA работает с абстракцией представления IView. Все классы View должны содержать реализацию IView.
- IView содержит события, которые требуют взаимодействия с моделью
- IView содержит контекст — ссылка на данные модели, которые необходимо отобразить пользователю
- View может содержать бизнес-логику, которая не требует взаимодействия с моделью. Например, если требуется реализовать из ALV проваливание в карточку контрагента, то данная логика будет относиться к представлению.
Приложение (Application):
- Выполняет роль связки представления и модели и является точкой входа в приложение.
- Имеет критерии запуска — набор параметров, которые определяют с какими параметрами необходимо запустить приложение. Обычно это параметры селекционного экрана.
- Критерии приложения состоят из критериев модели и представления. Например, если на селекционном экране требуется ввести дату проводки и указать флаг вывода отчета PDF или ALV, то дата проводки будет относиться к критериям модели, а флаг PDF и ALV к критериям представления.
- В конструктор приложения передаются критерии запуска. Приложение создает модель и представление, подписывается на события представления, связывает контекст представления с моделью.
Модель (Model):
- Содержит публичные атрибуты, которые необходимы представлению.
- Содержит критерии расчета модели и метод инициализации.
Реализация
В коде я буду придерживаться классических обозначений MVC, за исключением контроллера. Его буду называть Application или App.
В выборе между локальными и глобальными классами предпочтение отдаю последним. Использование глобальных классов позволит отказаться от SUBMIT и CALL TRANSACTION если потребуется вызывать программу из другой разработки.
В качестве примера рассмотрим задачу вывода движений документов материала. Упрощенная версия стандартной транзакции MB51.
Модель
Поля, необходимые для отображения определим в структуре ZSMVC_DEMO_OUTTAB.
Модель будет реализована в классе ZCL_MVC_DEMO_MODEL.
Для связи модели с представлением будет публичный атрибут.
Конструктор модели будет принимать критерии выбора данных (в данном случае это критерии экрана выбора).
В модели будет публичный метод для инициализации состояния модели.
Класс модели данных
CLASS zcl_mvc_demo_model DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF mts_criteria, matnr TYPE RANGE OF mseg-matnr, charg TYPE RANGE OF mseg-charg, budat TYPE RANGE OF mkpf-budat, END OF mts_criteria . DATA mt_matmove TYPE STANDARD TABLE OF zsmvc_demo_outtab WITH DEFAULT KEY. METHODS constructor IMPORTING !is_criteria TYPE mts_criteria . METHODS initialization . PROTECTED SECTION. PRIVATE SECTION. DATA ms_criteria TYPE mts_criteria . ENDCLASS. CLASS ZCL_MVC_DEMO_MODEL IMPLEMENTATION. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_MODEL->CONSTRUCTOR * +————————————————————————————————-+ * | [—>] IS_CRITERIA TYPE MTS_CRITERIA * +————————————————————————————— METHOD constructor. ms_criteria = is_criteria. ENDMETHOD. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_MODEL->INITIALIZATION * +————————————————————————————————-+ * +————————————————————————————— METHOD initialization. CLEAR mt_matmove[]. SELECT mseg~mblnr mseg~mjahr mseg~zeile mkpf~budat mkpf~blart mseg~matnr mseg~charg mseg~menge mseg~meins mseg~dmbtr mseg~waers INTO CORRESPONDING FIELDS OF TABLE mt_matmove FROM mseg JOIN mkpf ON mkpf~mblnr EQ mseg~mblnr AND mkpf~mjahr EQ mseg~mjahr WHERE mseg~matnr IN ms_criteria-matnr AND mseg~charg IN ms_criteria-charg AND mkpf~budat IN ms_criteria-budat. ENDMETHOD. ENDCLASS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
CLASS zcl_mvc_demo_model DEFINITION PUBLIC FINAL CREATE PUBLIC .
PUBLIC SECTION.
TYPES: BEGIN OF mts_criteria, matnr TYPE RANGE OF mseg-matnr, charg TYPE RANGE OF mseg-charg, budat TYPE RANGE OF mkpf-budat, END OF mts_criteria . DATA mt_matmove TYPE STANDARD TABLE OF zsmvc_demo_outtab WITH DEFAULT KEY.
METHODS constructor IMPORTING !is_criteria TYPE mts_criteria . METHODS initialization . PROTECTED SECTION. PRIVATE SECTION. DATA ms_criteria TYPE mts_criteria . ENDCLASS.
CLASS ZCL_MVC_DEMO_MODEL IMPLEMENTATION.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_MODEL->CONSTRUCTOR * +————————————————————————————————-+ * | [—>] IS_CRITERIA TYPE MTS_CRITERIA * +————————————————————————————— METHOD constructor. ms_criteria = is_criteria. ENDMETHOD.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_MODEL->INITIALIZATION * +————————————————————————————————-+ * +————————————————————————————— METHOD initialization. CLEAR mt_matmove[].
SELECT mseg~mblnr mseg~mjahr mseg~zeile mkpf~budat mkpf~blart mseg~matnr mseg~charg mseg~menge mseg~meins mseg~dmbtr mseg~waers INTO CORRESPONDING FIELDS OF TABLE mt_matmove FROM mseg JOIN mkpf ON mkpf~mblnr EQ mseg~mblnr AND mkpf~mjahr EQ mseg~mjahr WHERE mseg~matnr IN ms_criteria-matnr AND mseg~charg IN ms_criteria-charg AND mkpf~budat IN ms_criteria-budat. ENDMETHOD. ENDCLASS. |
Представление
Интерфейс представления (IView) будет содержать структуру с типом контекста (Context) и методы для установки контекста и отображения представления. Причем, все компоненты контекста будут ссылками.
Интерфейс представления IView
INTERFACE zif_mvc_demo_view PUBLIC . TYPES: mtt_outtab TYPE STANDARD TABLE OF zsmvc_demo_outtab WITH DEFAULT KEY, BEGIN OF mts_context, outtab TYPE REF TO mtt_outtab, END OF mts_context . DATA ms_context TYPE mts_context . METHODS set_context IMPORTING !is_context TYPE mts_context . METHODS display . ENDINTERFACE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
INTERFACE zif_mvc_demo_view PUBLIC . TYPES: mtt_outtab TYPE STANDARD TABLE OF zsmvc_demo_outtab WITH DEFAULT KEY, BEGIN OF mts_context, outtab TYPE REF TO mtt_outtab, END OF mts_context .
DATA ms_context TYPE mts_context .
METHODS set_context IMPORTING !is_context TYPE mts_context . METHODS display . ENDINTERFACE. |
Для примера рассмотрим две реализации IView: вывод отчета в формате ALV и в виде списка. Классы ZCL_MVC_DEMO_VIEW_ALV и ZCL_MVC_DEMO_VIEW_LIST соответственно.
Класс представления ALV
CLASS zcl_mvc_demo_view_alv DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_mvc_demo_view . PROTECTED SECTION. PRIVATE SECTION. ALIASES ms_context FOR zif_mvc_demo_view~ms_context . DATA mo_salv TYPE REF TO cl_salv_table . ENDCLASS. CLASS zcl_mvc_demo_view_alv IMPLEMENTATION. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_ALV->ZIF_MVC_DEMO_VIEW~DISPLAY * +————————————————————————————————-+ * +————————————————————————————— METHOD zif_mvc_demo_view~display. DATA lo_functions TYPE REF TO cl_salv_functions_list. DATA lo_columns TYPE REF TO cl_salv_columns_table. IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY. lo_functions = mo_salv->get_functions( ). lo_functions->set_all( abap_true ). lo_columns = mo_salv->get_columns( ). lo_columns->set_optimize( abap_true ). ENDIF. mo_salv->display( ). ENDMETHOD. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_ALV->ZIF_MVC_DEMO_VIEW~SET_CONTEXT * +————————————————————————————————-+ * | [—>] IS_CONTEXT TYPE MTS_CONTEXT * +————————————————————————————— METHOD zif_mvc_demo_view~set_context. IF ms_context IS NOT INITIAL. MESSAGE e674(ilm_stor). » Источник контекста уже установлен, двойное использование невозможно ELSE. ms_context = is_context. ENDIF. ENDMETHOD. ENDCLASS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
CLASS zcl_mvc_demo_view_alv DEFINITION PUBLIC FINAL CREATE PUBLIC .
PUBLIC SECTION. INTERFACES zif_mvc_demo_view . PROTECTED SECTION. PRIVATE SECTION. ALIASES ms_context FOR zif_mvc_demo_view~ms_context .
DATA mo_salv TYPE REF TO cl_salv_table . ENDCLASS.
CLASS zcl_mvc_demo_view_alv IMPLEMENTATION.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_ALV->ZIF_MVC_DEMO_VIEW~DISPLAY * +————————————————————————————————-+ * +————————————————————————————— METHOD zif_mvc_demo_view~display. DATA lo_functions TYPE REF TO cl_salv_functions_list. DATA lo_columns TYPE REF TO cl_salv_columns_table.
IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY.
lo_functions = mo_salv->get_functions( ). lo_functions->set_all( abap_true ).
lo_columns = mo_salv->get_columns( ). lo_columns->set_optimize( abap_true ). ENDIF.
mo_salv->display( ). ENDMETHOD.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_ALV->ZIF_MVC_DEMO_VIEW~SET_CONTEXT * +————————————————————————————————-+ * | [—>] IS_CONTEXT TYPE MTS_CONTEXT * +————————————————————————————— METHOD zif_mvc_demo_view~set_context. IF ms_context IS NOT INITIAL. MESSAGE e674(ilm_stor). » Источник контекста уже установлен, двойное использование невозможно ELSE. ms_context = is_context. ENDIF. ENDMETHOD. ENDCLASS. |
Реализация IView в виде списка во многом дублирует код View ALV. Это сделано для простоты понимания.
Класс представления в виде списка
CLASS zcl_mvc_demo_view_list DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_mvc_demo_view . PROTECTED SECTION. PRIVATE SECTION. ALIASES ms_context FOR zif_mvc_demo_view~ms_context . DATA mo_salv TYPE REF TO cl_salv_table . ENDCLASS. CLASS ZCL_MVC_DEMO_VIEW_LIST IMPLEMENTATION. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_LIST->ZIF_MVC_DEMO_VIEW~DISPLAY * +————————————————————————————————-+ * +————————————————————————————— METHOD zif_mvc_demo_view~display. DATA lo_functions TYPE REF TO cl_salv_functions_list. IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory EXPORTING list_display = abap_true IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY. lo_functions = mo_salv->get_functions( ). lo_functions->set_all( abap_true ). ENDIF. mo_salv->display( ). ENDMETHOD. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_LIST->ZIF_MVC_DEMO_VIEW~SET_CONTEXT * +————————————————————————————————-+ * | [—>] IS_CONTEXT TYPE MTS_CONTEXT * +————————————————————————————— METHOD zif_mvc_demo_view~set_context. IF ms_context IS NOT INITIAL. MESSAGE e674(ilm_stor). » Источник контекста уже установлен, двойное использование невозможно ELSE. ms_context = is_context. ENDIF. ENDMETHOD. ENDCLASS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
CLASS zcl_mvc_demo_view_list DEFINITION PUBLIC FINAL CREATE PUBLIC .
PUBLIC SECTION. INTERFACES zif_mvc_demo_view . PROTECTED SECTION. PRIVATE SECTION. ALIASES ms_context FOR zif_mvc_demo_view~ms_context . DATA mo_salv TYPE REF TO cl_salv_table . ENDCLASS.
CLASS ZCL_MVC_DEMO_VIEW_LIST IMPLEMENTATION.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_LIST->ZIF_MVC_DEMO_VIEW~DISPLAY * +————————————————————————————————-+ * +————————————————————————————— METHOD zif_mvc_demo_view~display. DATA lo_functions TYPE REF TO cl_salv_functions_list.
IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory EXPORTING list_display = abap_true IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY.
lo_functions = mo_salv->get_functions( ). lo_functions->set_all( abap_true ). ENDIF.
mo_salv->display( ). ENDMETHOD.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_VIEW_LIST->ZIF_MVC_DEMO_VIEW~SET_CONTEXT * +————————————————————————————————-+ * | [—>] IS_CONTEXT TYPE MTS_CONTEXT * +————————————————————————————— METHOD zif_mvc_demo_view~set_context. IF ms_context IS NOT INITIAL. MESSAGE e674(ilm_stor). » Источник контекста уже установлен, двойное использование невозможно ELSE. ms_context = is_context. ENDIF. ENDMETHOD. ENDCLASS. |
Приложение (контроллер)
Конструктор приложения принимает на вход критерии приложения (Criteria) и создает экземпляры Model и View, после чего связывает контекст представления с моделью. При этом, критерии приложения состоят из критериев модели и критериев представления. На этом этапе также следует подписывать приложение на события представления. Далее это будет подробно рассмотрено.
Класс приложения (контроллера)
CLASS zcl_mvc_demo_app DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES: BEGIN OF mts_criteria. INCLUDE TYPE zcl_mvc_demo_model=>mts_criteria AS model. TYPES: alv TYPE flag, list TYPE flag, END OF mts_criteria . METHODS constructor IMPORTING !is_criteria TYPE mts_criteria . METHODS run . PROTECTED SECTION. PRIVATE SECTION. DATA mo_model TYPE REF TO zcl_mvc_demo_model. DATA mo_view TYPE REF TO zif_mvc_demo_view. ENDCLASS. CLASS ZCL_MVC_DEMO_APP IMPLEMENTATION. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_APP->CONSTRUCTOR * +————————————————————————————————-+ * | [—>] IS_CRITERIA TYPE MTS_CRITERIA * +————————————————————————————— METHOD constructor. DATA ls_context TYPE zif_mvc_demo_view=>mts_context. mo_model = NEW #( is_criteria-model ). CASE abap_true. WHEN is_criteria-alv. mo_view = NEW zcl_mvc_demo_view_alv( ). WHEN is_criteria-list. mo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE. ls_context-outtab = REF #( mo_model->mt_matmove ). mo_view->set_context( ls_context ). ENDMETHOD. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_APP->RUN * +————————————————————————————————-+ * +————————————————————————————— METHOD run. mo_model->initialization( ). mo_view->display( ). ENDMETHOD. ENDCLASS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
CLASS zcl_mvc_demo_app DEFINITION PUBLIC FINAL CREATE PUBLIC .
PUBLIC SECTION. TYPES: BEGIN OF mts_criteria. INCLUDE TYPE zcl_mvc_demo_model=>mts_criteria AS model. TYPES: alv TYPE flag, list TYPE flag, END OF mts_criteria .
METHODS constructor IMPORTING !is_criteria TYPE mts_criteria . METHODS run . PROTECTED SECTION. PRIVATE SECTION. DATA mo_model TYPE REF TO zcl_mvc_demo_model. DATA mo_view TYPE REF TO zif_mvc_demo_view. ENDCLASS.
CLASS ZCL_MVC_DEMO_APP IMPLEMENTATION. * —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_APP->CONSTRUCTOR * +————————————————————————————————-+ * | [—>] IS_CRITERIA TYPE MTS_CRITERIA * +————————————————————————————— METHOD constructor. DATA ls_context TYPE zif_mvc_demo_view=>mts_context.
mo_model = NEW #( is_criteria-model ).
CASE abap_true. WHEN is_criteria-alv. mo_view = NEW zcl_mvc_demo_view_alv( ). WHEN is_criteria-list. mo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE. ls_context-outtab = REF #( mo_model->mt_matmove ). mo_view->set_context( ls_context ). ENDMETHOD.
* —————————————————————————————+ * | Instance Public Method ZCL_MVC_DEMO_APP->RUN * +————————————————————————————————-+ * +————————————————————————————— METHOD run. mo_model->initialization( ). mo_view->display( ). ENDMETHOD. ENDCLASS. |
Метод RUN приложения инициализирует состояние модели и отображает представление.
Основная программа
Основная программа будет содержать селекционный экран, его PBO/PAI логику и запуск контроллера с передачей ему параметров. Мне встречались реализации, где экран выбора представлен в виде отдельного MVC приложения, но код при этом становился более сложным и громоздким.
Код программы MVC
REPORT z_mvc_demo. TABLES: mseg, mkpf. SELECT-OPTIONS s_matnr FOR mseg-matnr. SELECT-OPTIONS s_charg FOR mseg-charg. SELECT-OPTIONS s_budat FOR mkpf-budat. PARAMETERS f_alv TYPE flag RADIOBUTTON GROUP gr0 DEFAULT ‘X’. PARAMETERS f_list TYPE flag RADIOBUTTON GROUP gr0. START-OF-SELECTION. PERFORM main. FORM main. DATA ls_criteria TYPE zcl_mvc_demo_app=>mts_criteria. DATA lo_app TYPE REF TO zcl_mvc_demo_app. ls_criteria-matnr = s_matnr[]. ls_criteria-charg = s_charg[]. ls_criteria-budat = s_budat[]. ls_criteria-alv = f_alv. ls_criteria-list = f_list. lo_app = NEW #( ls_criteria ). lo_app->run( ). ENDFORM.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
REPORT z_mvc_demo.
TABLES: mseg, mkpf.
SELECT-OPTIONS s_matnr FOR mseg-matnr. SELECT-OPTIONS s_charg FOR mseg-charg. SELECT-OPTIONS s_budat FOR mkpf-budat. PARAMETERS f_alv TYPE flag RADIOBUTTON GROUP gr0 DEFAULT ‘X’. PARAMETERS f_list TYPE flag RADIOBUTTON GROUP gr0.
START-OF-SELECTION. PERFORM main.
FORM main. DATA ls_criteria TYPE zcl_mvc_demo_app=>mts_criteria. DATA lo_app TYPE REF TO zcl_mvc_demo_app.
ls_criteria-matnr = s_matnr[]. ls_criteria-charg = s_charg[]. ls_criteria-budat = s_budat[]. ls_criteria-alv = f_alv. ls_criteria-list = f_list.
lo_app = NEW #( ls_criteria ). lo_app->run( ). ENDFORM. |
Тип структуры Criteria определен в самом классе App, а поля структуры критериев совпадают с параметрами селекционного экрана. В данном примере, параметры F_ALV и F_LIST определяют выбор представления, остальные параметры относятся к критериям модели.
Метод RUN приложения запускает программу. Запуск приложения можно сравнить с запуском транзакции с заранее определенными параметрами экрана. Это позволяет использовать ее из других программ без SUBMIT.
Примечание. Иногда бывает удобнее передать в App не Criteria, а экземпляры Model и View. В таком случае меняются входные параметры конструктора и создание соответствующих объектов выносится за пределы приложения.
Код программы MVC (альтернативный вариант)
FORM main. DATA ls_criteria TYPE z_mvc_demo_model=>mts_criteria. DATA lo_model TYPE REF TO zcl_mvc_demo_model. DATA lo_view TYPE REF TO zif_mvc_demo_view. DATA lo_app TYPE REF TO zcl_mvc_demo_app. ls_criteria-matnr = s_matnr[]. ls_criteria-charg = s_charg[]. ls_criteria-budat = s_budat[]. lo_model = NEW #( ls_criteria ). CASE abap_true. WHEN f_alv. lo_view = NEW zcl_mvc_demo_view_alv( ). WHEN f_list. lo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE. lo_app = NEW #( io_model = lo_model io_view = lo_view ). lo_app->run( ). ENDFORM.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
FORM main. DATA ls_criteria TYPE z_mvc_demo_model=>mts_criteria. DATA lo_model TYPE REF TO zcl_mvc_demo_model. DATA lo_view TYPE REF TO zif_mvc_demo_view. DATA lo_app TYPE REF TO zcl_mvc_demo_app.
ls_criteria-matnr = s_matnr[]. ls_criteria-charg = s_charg[]. ls_criteria-budat = s_budat[]. lo_model = NEW #( ls_criteria ).
CASE abap_true. WHEN f_alv. lo_view = NEW zcl_mvc_demo_view_alv( ). WHEN f_list. lo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE.
lo_app = NEW #( io_model = lo_model io_view = lo_view ). lo_app->run( ). ENDFORM. |
Селекционный экран
Представление в виде ALV таблицы
Представление в виде списка
Как реализовать сложную логику экрана
Проблемы классов в ABAP в том, что на них нельзя построить полноценный GUI. Ситуации, в которых стандартного CL_SALV_TABLE достаточно довольно редки. Поэтому, для определения GUI-заголовков/статусов и экранов следует создавать группу функций. ГФ будет тесно связана с View. По сути, она будет являться частью View.
Всю PBO и PAI логику должен обрабатывать класс View. При необходимости взаимодействия с Model, View должно вызывать событие, которое будет обрабатывать контроллер.
Расширение View
Допустим нам потребовалось расширить программу: добавить кнопку с обновлением данных, реализовать «проваливание» в MIGO по документу материала и в MM03 по коду ОЗМ.
Дальнейшие действия будем проводить только с ALV представлением, но на практике нужно будет адаптировать все реализации IView.
Для реализации данной задачу GUI логику перенесем в функциональный модуль Z_MVC_DEMO_VIEW_ALV_DISPLAY, который будет принимать ссылку на CL_SALV_TABLE.
В классе ZCL_MVC_DEMO_VIEW_ALV объявим обработчики событий SALV: ON_USER_COMMAND, ON_DOUBLE_CLICK. Метод DISPLAY будет создавать экземпляр CL_SALV_TABLE и подписываться на события. Управление по выводу GUI будет передаваться в Z_MVC_DEMO_VIEW_ALV_DISPLAY.
Код метода DISPLAY
METHOD zif_mvc_demo_view~display. DATA lo_event TYPE REF TO cl_salv_events_table. IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY. lo_event = mo_salv->get_event( ). SET HANDLER on_user_command FOR lo_event. SET HANDLER on_double_click FOR lo_event. ENDIF. CALL FUNCTION ‘Z_MVC_DEMO_VIEW_ALV_DISPLAY’ EXPORTING io_salv = mo_salv. ENDMETHOD.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
METHOD zif_mvc_demo_view~display. DATA lo_event TYPE REF TO cl_salv_events_table.
IF mo_salv IS NOT BOUND. TRY . CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = mo_salv CHANGING t_table = ms_context-outtab->*[]. CATCH cx_salv_msg INTO DATA(lx_salv_msg). MESSAGE lx_salv_msg TYPE rs_c_error. ENDTRY.
lo_event = mo_salv->get_event( ). SET HANDLER on_user_command FOR lo_event. SET HANDLER on_double_click FOR lo_event. ENDIF.
CALL FUNCTION ‘Z_MVC_DEMO_VIEW_ALV_DISPLAY’ EXPORTING io_salv = mo_salv. ENDMETHOD. |
В группу функций с представлением создаем GUI статус с кнопкой «Обновить» (REFRESH). В Z_MVC_DEMO_VIEW_ALV_DISPLAY устанавливаем указанный статус и отображаем ALV.
Код ФМ для отображения View в формате ALV
FUNCTION z_mvc_demo_view_alv_display. *»———————————————————————- *»*»Локальный интерфейс: *» IMPORTING *» REFERENCE(IO_SALV) TYPE REF TO CL_SALV_TABLE *»———————————————————————- CONSTANTS lc_pf_status TYPE sypfkey VALUE ‘MVC_DEMO_GUI_STATUS’. DATA lo_columns TYPE REF TO cl_salv_columns_table. IF abap_true IS INITIAL. SET PF-STATUS lc_pf_status. » Фиктивный вызов для журнала использования ELSE. io_salv->set_screen_status( report = sy-repid pfstatus = lc_pf_status set_functions = cl_salv_table=>c_functions_all ). ENDIF. lo_columns = io_salv->get_columns( ). lo_columns->set_optimize( abap_true ). io_salv->display( ). ENDFUNCTION.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
FUNCTION z_mvc_demo_view_alv_display. *»———————————————————————- *»*»Локальный интерфейс: *» IMPORTING *» REFERENCE(IO_SALV) TYPE REF TO CL_SALV_TABLE *»———————————————————————- CONSTANTS lc_pf_status TYPE sypfkey VALUE ‘MVC_DEMO_GUI_STATUS’. DATA lo_columns TYPE REF TO cl_salv_columns_table.
IF abap_true IS INITIAL. SET PF-STATUS lc_pf_status. » Фиктивный вызов для журнала использования ELSE. io_salv->set_screen_status( report = sy-repid pfstatus = lc_pf_status set_functions = cl_salv_table=>c_functions_all ). ENDIF.
lo_columns = io_salv->get_columns( ). lo_columns->set_optimize( abap_true ).
io_salv->display( ). ENDFUNCTION. |
Расширяем IView, добавляя в него событие REFRESH, которое будет обновлять модель
В контроллере делаем обработчик события Refresh и подписываемся на соответствующее событие IView.
Подписка на события IView
CLASS ZCL_MVC_DEMO_APP IMPLEMENTATION. … METHOD constructor. DATA ls_context TYPE zif_mvc_demo_view=>mts_context. mo_model = NEW #( is_criteria-model ). CASE abap_true. WHEN is_criteria-alv. mo_view = NEW zcl_mvc_demo_view_alv( ). WHEN is_criteria-list. mo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE. SET HANDLER refresh FOR mo_view. ls_context-outtab = REF #( mo_model->mt_matmove ). mo_view->set_context( ls_context ). ENDMETHOD. METHOD refresh. mo_model->refresh( ). ENDMETHOD. … ENDCLASS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
CLASS ZCL_MVC_DEMO_APP IMPLEMENTATION. … METHOD constructor. DATA ls_context TYPE zif_mvc_demo_view=>mts_context.
mo_model = NEW #( is_criteria-model ).
CASE abap_true. WHEN is_criteria-alv. mo_view = NEW zcl_mvc_demo_view_alv( ). WHEN is_criteria-list. mo_view = NEW zcl_mvc_demo_view_list( ). ENDCASE. SET HANDLER refresh FOR mo_view. ls_context-outtab = REF #( mo_model->mt_matmove ). mo_view->set_context( ls_context ). ENDMETHOD.
METHOD refresh. mo_model->refresh( ). ENDMETHOD. … ENDCLASS. |
Теперь настраиваем обработчик USER_COMMAND для View. При нажатии на кнопку «Обновить» вызываем событие обновления модели данных и обновляем View.
Обработка USER_COMMAND
METHOD on_user_command. CASE e_salv_function. WHEN ‘REFRESH’. RAISE EVENT refresh. mo_salv->refresh( ). WHEN OTHERS. ENDCASE. ENDMETHOD.
1 2 3 4 5 6 7 8 |
METHOD on_user_command. CASE e_salv_function. WHEN ‘REFRESH’. RAISE EVENT refresh. mo_salv->refresh( ). WHEN OTHERS. ENDCASE. ENDMETHOD. |
Таким образом View сама себя обновляет. Ни Model ни App никак не воздействуют на View. В ABAP программах View не может обновиться без взаимодействия пользователя. Эту возможность нужно использовать для ослабления связей View.
В обработчике события DOUBLE_CLICK настраиваем проваливание в MM03 при двойном клике на MATNR.
Обработка DOUBLE_CLICK
METHOD on_double_click. FIELD-SYMBOLS <ls> LIKE LINE OF ms_context-outtab->*[]. READ TABLE ms_context-outtab->*[] ASSIGNING <ls> INDEX row. CHECK sy-subrc EQ 0. CASE column. WHEN ‘MATNR’. SET PARAMETER ID ‘MAT’ FIELD <ls>-matnr. CALL TRANSACTION ‘MM03’ AND SKIP FIRST SCREEN. WHEN OTHERS. ENDCASE. ENDMETHOD.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
METHOD on_double_click. FIELD-SYMBOLS <ls> LIKE LINE OF ms_context-outtab->*[].
READ TABLE ms_context-outtab->*[] ASSIGNING <ls> INDEX row. CHECK sy-subrc EQ 0.
CASE column. WHEN ‘MATNR’. SET PARAMETER ID ‘MAT’ FIELD <ls>-matnr. CALL TRANSACTION ‘MM03’ AND SKIP FIRST SCREEN. WHEN OTHERS. ENDCASE. ENDMETHOD. |
Как можно заметить выше, проваливание в MM03 реализовано в самой View, хоть это можно отнести и к бизнес логике. На уровень View данная логика вынесена исходя из соображений: к модели не требуется обращаться за дополнительными данными; логика относится только к ALV, т.е. если бы была реализация View в виде Excel или PDF, то данное событие невозможно было бы обработать.
Аналогичным способом можно обработать сложную View с подэкранами и полями ввода/вывода. В таком случае PBO и PAI модули будут вызывать соответствующие методы View. При необходимости View будет отправлять события контроллеру.
Что такое, архитектура и пример
Автор: Мэтью Мартин
ЧасыОбновлено
Что такое MVC Framework?
Платформа Модель-Представление-Контроллер (MVC) — это архитектурный шаблон, который разделяет приложение на три основных логических компонента: Модель, Представление и Контроллер. Отсюда и аббревиатура MVC. Каждый компонент архитектуры предназначен для обработки определенного аспекта разработки приложения. MVC отделяет бизнес-логику и уровень представления друг от друга. Он традиционно использовался для настольных графических пользовательских интерфейсов (GUI). В настоящее время архитектура MVC в веб-технологиях стала популярной для разработки веб-приложений, а также мобильных приложений.
В этом руководстве по MVC вы узнаете больше об основах MVC.
- История MVC
- Особенности MVC
- Архитектура MVC
- Примеры MVC
- Популярные веб-фреймворки MVC
- Преимущества MVC: основные преимущества
- Недостатки использования MVC
- Трехуровневая архитектура и архитектура MVC
История MVC
- Архитектура MVC впервые обсуждалась в 1979 Трюгве Реенскауг Модель
- MVC была впервые представлена в 1987 году в языке программирования Smalltalk.
- MVC впервые был принят в качестве общей концепции в статье 1988 года.
- В последнее время шаблон MVC широко используется в современных веб-приложениях
Особенности MVC
- Простая проверка без трения. Хорошо тестируемый, расширяемый и подключаемый фреймворк
- Для разработки архитектуры веб-приложения с использованием шаблона MVC он предлагает полный контроль над вашим HTML, а также вашими URL-адресами
- Использовать существующие функции, предоставляемые ASP.NET, JSP, Django и т. д.
- Четкое разделение логики: Модель, Представление, Контроллер. Разделение прикладных задач, т.е. бизнес-логика, логика Ul и логика ввода
- Маршрутизация URL-адресов для SEO-дружественных URL-адресов. Мощное сопоставление URL-адресов для понятных и доступных для поиска URL-адресов
- Поддержка разработки через тестирование (TDD)
Архитектура MVC
Вот подробная архитектура инфраструктуры MVC:
Три важных компонента MVC:
- Модель: включает все данные и связанную с ними логику
- View: представление данных пользователю или обработка взаимодействия с пользователем
- Контроллер: интерфейс между компонентами модели и представления
Давайте подробно рассмотрим этот компонент:
Представление
Представление — это та часть приложения, которая представляет представление данных.
Представления создаются на основе данных, собранных из данных модели. Представление запрашивает у модели информацию, чтобы она представляла выходное представление пользователю.
Представление также представляет данные из диаграмм, диаграмм и таблиц. Например, любое представление клиента будет включать в себя все компоненты пользовательского интерфейса, такие как текстовые поля, раскрывающиеся списки и т. д.
Контроллер
Контроллер — это часть приложения, которая обрабатывает взаимодействие с пользователем. Контроллер интерпретирует ввод данных пользователем с помощью мыши и клавиатуры, информируя модель и представление о необходимых изменениях.
Контроллер отправляет команды модели для обновления ее состояния (например, сохранение определенного документа). Контроллер также отправляет команды связанному с ним представлению, чтобы изменить представление представления (например, прокрутка определенного документа).
Модель
Компонент модели хранит данные и связанную с ними логику. Он представляет данные, которые передаются между компонентами контроллера или любой другой связанной бизнес-логикой. Например, объект Controller будет извлекать информацию о клиенте из базы данных. Он манипулирует данными и отправляет обратно в базу данных или использует их для отображения тех же данных.
Он отвечает на запрос представлений, а также отвечает на инструкции контроллера по обновлению. Это также самый нижний уровень шаблона, который отвечает за сохранение данных.
Примеры MVC
Давайте посмотрим пример Model View Controller из повседневной жизни:
Пример 1:
- Предположим, вы идете в ресторан. Вы не пойдете на кухню и не приготовите еду, которую наверняка сможете приготовить дома. Вместо этого вы идете туда и ждете, пока подойдет официант.
- Сейчас к вам подходит официант, и вы заказываете еду. Официант не знает, кто вы и что вы хотите, он просто записал детали вашего заказа на еду.
- Затем официант идет на кухню. На кухне официант не готовит еду.
- Повар готовит вам еду. Официанту передается ваш заказ вместе с номером вашего столика.
- Повар приготовил для вас еду. Он использует ингредиенты для приготовления пищи. Предположим, вы заказываете сэндвич с овощами. Затем ему нужны хлеб, помидоры, картофель, стручковый перец, лук, биточки, сыр и т. д., которые он достает из холодильника .
- Повар передал еду официанту. Теперь работа официанта заключается в том, чтобы вынести эту еду за пределы кухни.
- Теперь официант знает, какие блюда вы заказали и как они поданы.
В этом примере архитектуры MVC
View = You Официант = Контроллер Кук = Модель Холодильник = Данные
Давайте посмотрим еще один пример модели MVC,
Пример 2:
Механизм привода автомобиля является еще одним примером модели MVC.
- Каждый автомобиль состоит из трех основных частей.
- Вид= Пользовательский интерфейс: (Рычаг переключения передач, панели, рулевое колесо, тормоз и т. д.)
- Контроллер-механизм (двигатель) Модель
- — Хранение (бензиновый или дизельный бак)
Автомобиль работает от двигателя, берет топливо из хранилища, но работает только с использованием указанных устройств пользовательского интерфейса.
Популярные веб-фреймворки MVC
Вот список некоторых популярных фреймворков MVC:
- Ruby on Rails
- Джанго
- ТортPHP
- Yii
- CherryPy
- Весна МВК
- Катализатор
- Рельсы
- Zend Framework
- CodeIgniter
- Ларавель
- Топливо PHP
- Симфония
Преимущества MVC: Основные преимущества
Вот основные преимущества использования архитектуры MVC:
- Простое обслуживание кода, которое легко расширять и расширять
- Компонент модели MVC можно тестировать отдельно от пользователя
- Упрощенная поддержка новых типов клиентов
- Разработка различных компонентов может выполняться параллельно.
- Это поможет вам избежать сложности, разделив приложение на три части. Модель, вид и контроллер
- Он использует только шаблон переднего контроллера, который обрабатывает запросы веб-приложений через один контроллер.
- Предлагает лучшую поддержку для разработки через тестирование
- Хорошо подходит для веб-приложений, которые поддерживаются большими группами веб-дизайнеров и разработчиков.
- Обеспечивает четкое разделение проблем (SoC).
- Поисковая оптимизация (SEO).
- Все классы и объекты независимы друг от друга, поэтому их можно тестировать по отдельности. Шаблон проектирования
- MVC позволяет логически группировать связанные действия на контроллере вместе.
Недостатки использования MVC
- Сложность чтения, изменения, модульного тестирования и повторного использования этой модели
- Навигация по платформе иногда может быть сложной, поскольку она вводит новые уровни абстракции, которые требуют от пользователей адаптации к критериям декомпозиции MVC.
- Нет формальной поддержки проверки
- Повышенная сложность и неэффективность данных
- Сложность использования MVC с современным пользовательским интерфейсом
- Для параллельного программирования требуется несколько программистов.
- Требуется знание нескольких технологий.
- Обслуживание множества кодов в контроллере
Трехуровневая архитектура и архитектура MVC
Параметр | Трехуровневая архитектура | Архитектура MVC |
---|---|---|
Связь | Этот тип шаблона архитектуры никогда не связывается напрямую с уровнем данных. | Все уровни обмениваются данными напрямую, используя треугольную топологию. |
Использование | 3 уровня: широко используется в веб-приложениях, где клиент, уровни данных и промежуточное ПО работают на физически отдельных платформах. | Обычно используется в приложениях, работающих на одной графической рабочей станции. |
Сводка
- MVC — это архитектурный шаблон, который разделяет приложение на 1) модель, 2) представление и 3) контроллер Модель
- : включает все данные и связанную с ними логику.
- View: представление данных пользователю или обработка взаимодействия с пользователем
- Контроллер: интерфейс между компонентами модели и представления
- Архитектура MVC впервые была обсуждена в 1979 году Трюгве Реенскаугом .
- Архитектура MVC на Java — это хорошо тестируемая, расширяемая и подключаемая платформа
- Некоторыми популярными платформами MVC являются Rails, Zend Framework, CodeIgniter, Laravel, Fuel PHP и т. д.
MVC Framework Introduction — GeeksforGeeks
За последние несколько лет веб-сайты перешли от простых HTML-страниц с небольшим количеством CSS к невероятно сложным приложениям, над которыми одновременно работают тысячи разработчиков. Для работы с этими сложными веб-приложениями разработчики используют различные шаблоны проектирования для компоновки своих проектов, чтобы сделать код менее сложным и с ним было проще работать. Наиболее популярным из этих шаблонов является MVC 9.0011 , также известный как Контроллер представления модели.
Платформа Модель-Представление-Контроллер (MVC) представляет собой шаблон архитектуры/проектирования, который разделяет приложение на три основных логических компонента: Модель , Представление и Контроллер . Каждый архитектурный компонент предназначен для обработки конкретных аспектов разработки приложения. Он изолирует бизнес-логику и уровень представления друг от друга. Традиционно использовался для рабочего стола графические пользовательские интерфейсы (GUI) . В настоящее время MVC является одной из наиболее часто используемых стандартных отраслевых сред веб-разработки для создания масштабируемых и расширяемых проектов. Он также используется для разработки мобильных приложений.
MVC был создан Trygve Reenskaug . Основная цель этого шаблона проектирования состояла в том, чтобы решить проблему пользователей, управляющих большим и сложным набором данных, путем разделения большого приложения на определенные разделы, каждый из которых имеет свое собственное назначение.
Особенности MVC:
- Он обеспечивает четкое разделение бизнес-логики, логики Ul и логики ввода.
- Он предлагает полный контроль над вашим HTML и URL-адресами, что упрощает разработку архитектуры веб-приложений.
- Это мощный компонент сопоставления URL-адресов, с помощью которого мы можем создавать приложения с понятными и доступными для поиска URL-адресами.
- Поддерживает Test Driven Development (TDD).
Компоненты MVC:
Фреймворк MVC включает в себя следующие 3 компонента:
- Контроллер
- Модель
- Просмотр
MVC Architecture Design
Controller:
. Контроллер IS Computer IS Componiter IS The Compontection. и модель, поэтому она выступает в качестве посредника. Контроллеру не нужно беспокоиться об обработке логики данных, он просто говорит модели, что делать. Он обрабатывает всю бизнес-логику и входящие запросы, манипулирует данными с помощью Model и взаимодействуйте с View , чтобы отобразить окончательный результат.
View:
Компонент View используется для всей логики пользовательского интерфейса приложения. Он генерирует пользовательский интерфейс для пользователя. Представления создаются данными, которые собираются компонентом модели, но эти данные берутся не напрямую, а через контроллер. Он взаимодействует только с компилятором.
Модель:
Модель 9Компонент 0012 соответствует всей логике, связанной с данными, с которой работает пользователь. Это могут быть либо данные, которые передаются между компонентами View и Controller, либо любые другие данные, связанные с бизнес-логикой. Он может добавлять или извлекать данные из базы данных. Он отвечает на запрос контроллера, потому что сам контроллер не может взаимодействовать с базой данных. Модель взаимодействует с базой данных и возвращает требуемые данные контроллеру.
Давайте разберемся с работой фреймворка MVC на примере:
Давайте представим, что конечный пользователь отправляет запрос на сервер, чтобы получить список студентов, обучающихся в классе. Затем сервер отправит этот запрос тому конкретному контроллеру, который обслуживает студентов. Затем этот контроллер запрашивает модель, которая обрабатывает студентов, чтобы вернуть список всех студентов, обучающихся в классе.
Поток данных в компонентах MVC
Модель запросит в базе данных список всех студентов, а затем вернет этот список обратно в контроллер. Если ответ от модели был успешным, то контроллер попросит представление, связанное со студентами, вернуть представление списка студентов. Это представление берет список студентов из контроллера и преобразует список в HTML, который может использоваться браузером.
Затем контроллер берет эту презентацию и возвращает ее пользователю. Таким образом, заканчивая запрос. Если ранее модель возвращала ошибку, контроллер обрабатывал эту ошибку, запрашивая представление, которое обрабатывает ошибки, для отображения этой конкретной ошибки. Эта презентация ошибки затем будет возвращена пользователю вместо презентации списка студентов.
Как видно из приведенного выше примера, модель обрабатывает все данные. Представление обрабатывает все представления, а контроллер просто сообщает модели и представлению, что делать. Это базовая архитектура и работа фреймворка MVC.
Преимущества MVC:
- Коды просты в обслуживании и легко расширяются.
- Компонент MVC модели можно протестировать отдельно.
- Компоненты MVC можно разрабатывать одновременно.
- Снижает сложность за счет разделения приложения на три части. Модель, представление и контроллер.
- Поддерживает Test Driven Development (TDD).
- Хорошо подходит для веб-приложений, которые поддерживаются большими группами веб-дизайнеров и разработчиков.
- Эта архитектура помогает тестировать компоненты независимо друг от друга, поскольку все классы и объекты не зависят друг от друга.
Недостатки MVC:
- Эту модель трудно читать, изменять, тестировать и повторно использовать.
- Она не подходит для создания небольших приложений.
- Неэффективность доступа к данным ввиду.
- Навигация по фреймворку может быть сложной, поскольку она вводит новые уровни абстракции, которые требуют от пользователей адаптации к критериям декомпозиции MVC.
- Повышенная сложность и неэффективность данных
Популярные платформы MVC:
Некоторые из наиболее популярных и широко используемых платформ MVC перечислены ниже.
- Ruby on Rails
- Django
- CherryPy
- Spring MVC
- Catalyst
- Rails
- Zend Framework
- Fuel PHP
- Laravel
- Symphony
MVC is generally used on applications that run on единая графическая рабочая станция. Разделение логических компонентов обеспечивает удобочитаемость и модульность, а также делает более удобной часть тестирования.
Архитектура Model-View-Controller (MVC) для приложений Node
MVC — это аббревиатура от Model-View-Controller. Это шаблон проектирования для программных проектов. Он используется в основном разработчиками Node, а также пользователями фреймворков C#, Ruby, PHP. В шаблоне MVC приложение и его разработка разделены на три взаимосвязанные части. Преимущество этого заключается в том, что он помогает сосредоточиться на определенной части имени приложения, способах представления информации пользователю и приема от него. Это помогает обеспечить эффективное повторное использование кода и параллельную разработку приложения. Даже если структура проекта может немного отличаться от идеальной структуры MVC, основной поток программы в приложении и из него остается прежним. В этом посте будет показан поток программы между этими компонентами приложения путем создания демонстрационного приложения. Сначала , давайте разберемся, что означают эти части приложения и какие функции они выполняют.
Объяснение
Модель : Модель представляет структуру данных, формат и ограничения, с которыми они хранятся. Он поддерживает данные приложения. По сути, это часть базы данных приложения. View : View — это то, что предоставляется пользователю. Представления используют модель и представляют данные в той форме, в которой хочет пользователь. Пользователю также может быть разрешено вносить изменения в данные, представленные пользователю. Они состоят из статических и динамических страниц, которые отображаются или отправляются пользователю, когда пользователь их запрашивает. Контроллер :Контроллер контролирует запросы пользователя и затем генерирует соответствующий ответ, который передается средству просмотра. Обычно пользователь взаимодействует с представлением, которое в свою очередь генерирует соответствующий запрос, этот запрос будет обрабатываться контроллером. Контроллер отображает соответствующее представление с данными модели в качестве ответа. Итак, резюмируя:
- Модель — это часть данных.
- Вид является частью пользовательского интерфейса.
- Контроллер является обработчиком запроса-ответа.
Архитектура MVC
Теперь давайте начнем с приложения . npm init используется здесь для создания файлов package.json и app.js .
npm-init
Как следует из названия, есть три папки, называемые моделями, представлениями и контроллерами, которые помогут в реализации архитектуры mvc. npm используется для установки базовых пакетов npm для начала работы.
npm-package-install-snip
Структура проекта выглядит следующим образом.
mvc-project-structure snip
Структура проекта Объяснение
- Как видите, есть папка маршрутов , которая будет служить контроллерами .
- Затем есть папка models , в которой у нас есть пользователь model .
- просматривает папку , в которой есть наши представления с расширением .handlebars . Обратите внимание, что handlebars — это механизм шаблонов, что означает, что он может генерировать страницы, заполняя созданные нами шаблоны.
Теперь давайте приступим к демонстрации того, как шаблон MVC реализуется для процесса входа в систему и регистрации в качестве пользователя в этом демо-приложении LoginApp.
- Напишите узел app.js , чтобы запустить приложение. Приложение запустится, если все правильно, в противном случае попробуйте отладить приложение, используя stackoverflow и тому подобное.
- Откройте приложение в браузере. Если вы разветвили и используете мой репозиторий github, перейдите по адресу localhost:3000 в своем браузере, и вы увидите работающее приложение. Когда вы откроете приложение в своем браузере, ваш файл app.js скажет себе что-то вроде: «Ой! Браузер запросил localhost:3000/ , поэтому давайте найдем файл, который будет обслуживаться, если этот маршрут будет использован. Он ищет этот код:
App use route appjs
- . Он сообщает приложению, что нужно использовать переменные маршруты, если запрашивается ‘/’ . Затем он ищет переменную маршрута. Он находит его в файле app.js здесь:
Маршрутам требуется
- . Теперь он просматривает файл gfgIndex.js в папке маршрутов нашего приложения node, чтобы найти код, который будет выполняться при попадании маршрута «/». Он находит следующий код.
Файл маршрутов GfgIndexjs
- Этот код в основном говорит, что рендерит index.hanblebars , если пользователь вошел в систему. Чтобы проверить, вошел ли пользователь в систему, он запускает функцию sureAuthenticated . Эта функция в основном говорит, что если пользователь вошел в систему, визуализировать файл index.handlebars , иначе перенаправить пользователя на маршрут /users/login .
Фрагмент маршрута входа GfgUsersjs
- Этот код указывает приложению отображать файл index.handlebars при вызове GET ‘/’. Итак, теперь он идет в папку представлений и ищет index.handlebars и отображает его пользователю. Вот как в приложении работает часть архитектуры контроллера представлений. Я полагаю, что приведенный выше алгоритм программы понятен читателю.
- Давайте перейдем к http://localhost:3000/users/register . Итак, приложение разбивает маршрут на две части: /users и /register и спрашивает себя что-то вроде «О, хорошо! Пользователи хотят видеть маршрут /users , а затем /register . Приложение ищет ‘/users’ в своем файле app.js и находит его здесь.
Приложение использует маршрут appjs
- . Затем он ищет переменную «users», которая будет использоваться при переходе по пути /users, которую можно найти в файле app.js:
Routes required
- . Итак, он переходит к файлу gfgUsers.js в папке маршрутов и ищет маршрут /register. Обратите внимание, что /users/register находится в файле gfgUsers.js как /register . Он просит браузер отобразить ‘register.handlebars’ файл. Это арка контроллера представления. реализация идет. Вторая часть регистрации Теперь давайте зарегистрируем нового пользователя.
Зарегистрируйте новую пользовательскую привязку. изображение: https://media.geeksforgeeks.org/wp-content/uploads/register-a-new-user-snap.png
- После нажатия на кнопку «Отправить» данные принимаются, POST изменен на ‘ /register’ маршрут для обработки. Этот контроллер проверяет входящие данные на наличие ошибок, а затем создает новую переменную с именем newUser со значением User 9.0011 смоделировал со всеми данными и вызовами save() для фактического сохранения данных пользователю.
Новая пользовательская консоль вошла в терминал
- После создания пользователя контроллер ‘/register’ запрашивает у браузера перенаправление пользователя на страницу ‘/login’ . Это реализация архитектуры модель-представление-контроллер.
Полный код, использованный в этой статье, можно найти здесь. Форкайте, клонируйте и запускайте.
Объяснение Model-View-Controller (MVC) — с помощью Legos — Real Python
Чтобы продемонстрировать, как веб-приложение, структурированное с использованием шаблона Model-View-Controller (или MVC ), работает на практике, давайте совершим путешествие вниз переулок памяти…
Лего!
Тебе десять лет, ты сидишь на полу своей гостиной, а перед тобой большое ведро Лего. Есть Лего самых разных форм и размеров. Некоторые синие, высокие и длинные. Как тракторный прицеп. Некоторые красные и почти кубической формы. А некоторые желтые — большие широкие плоскости, как листы стекла. Со всеми этими различными типами Lego невозможно сказать, что вы могли бы построить.
Но сюрприз, сюрприз, уже есть запрос . Твой старший брат подбегает и говорит: «Эй! Построй мне космический корабль!»
«Хорошо, — думаете вы, — это действительно может быть круто!» Космический корабль это.
Итак, вы приступили к работе. Вы начинаете доставать Лего, которые, по вашему мнению, вам понадобятся. Некоторые большие, некоторые маленькие. Разные цвета снаружи космического корабля, разные цвета двигателей. О, и разные цвета для бластерных пушек. (У вас должны быть бластерные пушки!)
Теперь, когда у вас есть все строительных блоков , пришло время собрать космический корабль. И вот после нескольких часов напряженной работы перед вами теперь — космический корабль!
Вы бежите на поиски брата, чтобы показать ему готовый продукт. «Вау, хорошая работа!», — говорит он. «Ха, — думает он, — я просто попросил об этом несколько часов назад, мне не нужно было ничего делать, и вот оно. Я желаю , чтобы все было так просто».
Что, если бы я сказал вам, что создание веб-приложения точно такое же, как сборка из Lego?
Удалить рекламу
Все начинается с запроса
…В случае с Лего, это твой брат попросил тебя что-то построить. В случае веб-приложения пользователь вводит URL-адрес, запрашивая просмотр определенной страницы.
Значит, твой брат пользователь.
Запрос доходит до контроллера
…С Лего вы управляете.
Контроллер отвечает за захват всех необходимых строительных блоков и организовать их по мере необходимости.
Эти строительные блоки известны как модели
…Различные типы LEGO являются моделями. У вас есть все разные размеры и формы, и вы берете те, которые вам нужны, чтобы построить космический корабль. В веб-приложении модели помогают контроллеру извлекать всю необходимую информацию из базы данных.
Итак, запрос приходит…
Контроллер (вы) получает запрос.
Он отправляется к моделям (Лего), чтобы получить необходимые предметы.
Теперь все готово для производства конечного продукта.
Конечный продукт известен как вид
…Космический корабль — это вид. Это конечный продукт, который в конечном итоге показывается тому, кто сделал запрос (вашему брату).
В веб-приложении представление — это последняя страница, которую пользователь видит в своем браузере.
Подводя итог…
При сборке из Lego:
- Ваш брат просит вас построить космический корабль.
- Вы получили запрос.
- Вы собираете и собираете все детали Лего, необходимые для постройки космического корабля.
- Вы используете лего, чтобы построить космический корабль и вернуть готовый космический корабль своему брату.
И в веб-приложении:
- Пользователь запрашивает просмотр страницы, вводя URL-адрес.
- Контроллер получает этот запрос.
- Он использует модели для получения всех необходимых данных, систематизирует их и отправляет в…
- View , который затем использует эти данные для отображения окончательной веб-страницы, представленной пользователю в его браузере.
Удалить рекламу
С более технической точки зрения
Обобщив функциональность MVC, давайте углубимся и посмотрим, как все работает на более техническом уровне.
Когда вы вводите в браузере URL-адрес для доступа к веб-приложению, вы отправляете запрос на просмотр определенной страницы в приложении. Но как приложение узнает, какую страницу отображать/рендерить?
При создании веб-приложения вы определяете так называемые маршруты . Маршруты — это, по сути, шаблоны URL, связанные с разными страницами. Поэтому, когда кто-то вводит URL-адрес, за кулисами приложение пытается сопоставить этот URL-адрес с одним из этих предопределенных маршрутов.
Итак, на самом деле в игре четыре основных компонента : маршрутов , моделей , представлений и контроллеров .
Маршруты
Каждый маршрут связан с контроллером, точнее с определенной функцией в контроллере , известном как действие контроллера . Таким образом, когда вы вводите URL-адрес, приложение пытается найти соответствующий маршрут и, в случае успеха, вызывает связанное с этим маршрутом действие контроллера.
В качестве примера рассмотрим базовый маршрут Flask:
@app.route('/') определение main_page(): проходить
Здесь мы устанавливаем маршрут /
, связанный с функцией просмотра main_page()
.
и контроллеры
В рамках действия контроллера обычно происходят две основные вещи: модели используются для извлечения всех необходимых данных из базы данных; и эти данные передаются представлению, которое отображает запрошенную страницу. Данные, полученные с помощью моделей, обычно добавляются в структуру данных (такую как список или словарь), и именно эта структура отправляется в представление.
Назад к нашему примеру Flask:
@app.route('/') определение main_page(): """Выполняет поиск записей в базе данных, а затем отображает их.""" БД = получить_БД() cur = db.execute('выберите * из записей, упорядоченных по id desc') записи = cur.fetchall() вернуть render_template («index.html», записи = записи)
Теперь в функции просмотра мы получаем данные из базы данных и выполняем некоторую базовую логику. Это возвращает список, который мы назначаем переменной , элементы
доступны в шаблоне index.html .
просмотров
Наконец, в представлении осуществляется доступ к этой структуре данных, и содержащаяся в ней информация используется для отображения HTML-содержимого страницы, которую пользователь в конечном итоге видит в своем браузере.
Опять же, вернемся к нашему приложению Flask, мы можем просмотреть записей
, каждая из которых отображается с использованием синтаксиса Jinja:
{% для записи в записи %}
{{ запись.название }}
Резюме
Итак, более подробное техническое описание процесса запроса MVC выглядит следующим образом:
- Пользователь запрашивает просмотр страницы, вводя URL-адрес.
- Приложение сопоставляет URL с предопределенным маршрутом .
- Вызывается действие контроллера , связанное с маршрутом.
- Действие контроллера использует модели для извлечения всех необходимых данных из базы данных, помещает данные в массив и загружает представление , передавая структуру данных.
- Представление получает доступ к структуре данных и использует ее для отображения запрошенной страницы, которая затем представляется пользователю в его браузере.
Это гостевой пост Алекса Коулмана, инструктора по программированию и веб-разработчика-консультанта.
Архитектура MVC за 5 минут: руководство для начинающих
Главная/Блог/Архитектура MVC за 5 минут: руководство для начинающих
11 мая 2020 г. — чтение за 5 мин. шаблон проектирования, который можно использовать во многих средах со многими языками программирования, обычно Python, Ruby, PHP, JavaScript и другими. Он широко используется для разработки веб-приложений и мобильных приложений.
В этом сообщении блога определяется концепция шаблона проектирования программного обеспечения Модель-Представление-Контроллер (MVC) и приводится базовый пример Модель-Представление-Контроллер в JavaScript/HTML/CSS.
Сегодня мы рассмотрим:
- Что такое архитектура MVC?
- Преимущества MVC
- Веб-приложение как MVC
- Разделение интересов
- Пример кода MVC
- Ресурсы
Что такое архитектура MVC?
Компоненты архитектуры шаблона MVC предназначены для обработки различных аспектов разрабатываемого приложения. Шаблон проектирования MVC служит для отделения уровня представления от бизнес-логики.
Почему разработчики заботятся о MVC? MVC популярен в разработке приложений и веб-приложений, и это один из наиболее широко используемых шаблонов проектирования программного обеспечения для приложений и веб-разработки. Шаблон проектирования Model View Controller разделяет задачи на одну из 3 групп:
- Model
- View
- Controller
Шаблон проектирования Model View Controller: разделение задач
Архитектурный шаблон Model View Controller разделяет задачи на одну из 3 ведра:
- Модель: хранит данные и управляет ими.
Часто это база данных, в нашем быстром примере мы будем использовать локальное веб-хранилище в браузере, чтобы проиллюстрировать концепцию.
- Вид: Графический интерфейс пользователя
Представление — это визуальное представление данных, например диаграмма, диаграмма, таблица, форма.
Представление содержит все функции, непосредственно взаимодействующие с пользователем, например нажатие кнопки или событие ввода.
- Контроллер: Мозги приложения.
Контроллер соединяет модель и вид. Контроллер преобразует входные данные из представления в запросы на получение/обновление данных в модели.
Контроллер получает входные данные от представления, использует логику для преобразования ввода в запрос модели, модель получает данные, контроллер передает данные из модели обратно в представление, чтобы пользователь мог просмотреть их в удобном виде.
Преимущества MVC
- Традиционно используется для графических пользовательских интерфейсов (GUI)
- Популярен в веб-приложениях
- MVC распределяет обязанности между клиентом и сервером, совместим с архитектурой веб-приложений
- MVC является полезным шаблоном проектирования при планировании разработки
- Разделение проблем: этот код разделен в зависимости от функции на модель, представление или сегмент контроллера
- Хорошо работает с Ruby on Rails
- Слабая связь
- Удаляет ненужные зависимости
- Возможность повторного использования без модификации
- MVC позволяет повторно использовать классы моделей без модификации
- Повторное использование кода
- Расширяемый код
- Высокая связность
- Проще поддерживать или модифицировать 170 частей 80 180 представлений 180 9090 Каждая часть может быть протестирована независимо 180 18
(Модель, вид, контроллер)
Веб-приложение как MVC
Вы можете думать о веб-приложении как о конструкции контроллера представления модели. MVC популярен в веб-приложениях, одна из причин в том, что обязанности разделены между клиентом и сервером.
Разделение задач
Дизайн MVC позволяет разделить задачи — разделить логику между 3 сегментами, чтобы каждый сегмент мог действовать независимо.
Модель, представление и контроллер не зависят друг от друга. Почему это важно? Как правило, над программным обеспечением работают команды — в команде могут быть дизайнер, инженер и архитектор базы данных. Разделение задач означает, что каждый член команды может работать над своей частью одновременно, потому что логика разделена на сегменты. Разделение проблем также отлично подходит для обслуживания — разработчики могут исправить ошибку в одном фрагменте кода, не проверяя другие фрагменты кода.
Слабосвязанный
Слабосвязанный означает, что каждая часть: модель, представление и контроллер действуют независимо друг от друга.
Разработчики могут изменить одну из частей, а остальные 2 части должны продолжать работать и не требуют модификации. При разработке программного обеспечения MVC логика в каждом из трех сегментов независима. Все в представлении действует независимо от модели — и наоборот, представление не будет иметь никакой логики, зависящей от модели.
Создание независимых моделей и представлений упрощает организацию кода и упрощает его обслуживание. Программисты могут исправить ошибку в представлении без изменения кода модели.
Дизайн MVC: как пользователь видит MVC
MVC с действием пользователя
На рисунках выше показано, что происходит в веб-приложении MVC, когда пользователь нажимает кнопку, с точки зрения пользователя.
Продолжайте изучать веб-приложения
Изучите основы JavaScript, обхода DOM и обработки событий в одном месте.
Образовательные интерактивные текстовые курсы предоставляют всю необходимую информацию в одном месте без необходимости просмотра видео.
Полный курс JavaScript: создание реального приложения с нуля
Пример кода MVC
В нашем простом примере мы будем хранить данные в браузере. В веб-приложении производственного качества данные будут храниться в базе данных.
Модель
В нашем примере с «Игрой престолов» модель — это поддельная база данных, в которой перечислены дома и персонажи. Обычно мы не пишем это как список на JavaScript, потому что поклонники GOT знают, что список может быть очень длинным, но это самый простой способ продемонстрировать в блоге.
Представление
Представление — это то, что вы видите в окне «Вывод» — это визуальное представление данных, которое удобно отображается для пользователей. В нашем случае селектор выпадающего списка.
Контроллер
Контроллер — это мозг нашего приложения — JavaScript, который обрабатывает событие щелчка. Контроллер принимает событие, обрабатывает его и ищет правильную информацию из модели — в нашем примере членов, связанных с каждым домом. Контроллер возвращает информацию в представление для отображения.
Примечание : Перед тестированием кода запустите его, нажав кнопку
RUN
. Затем вы можете нажать кнопкуTEST
. В противном случае тест-кейсы не пройдут.Код для этого упражнения взят из Полного курса JavaScript.
Что узнать дальше
Поздравляем с завершением первого знакомства с архитектурой MVC. Сегодня мы рассмотрели основы MVC, рассказали о преимуществах и завершили собственный пример проекта.
Однако это всего лишь одна концепция, которая вам понадобится, чтобы стать разработчиком веб-приложений.
Следующие темы для изучения:
- Обход DOM
- Изменение структуры страницы
- Дополнительные реактивные события
- Анимированные элементы
Приятного обучения!
Продолжить чтение о веб-приложениях
- Как разработать веб-приложение: архитектура программного обеспечения 101
- Создавайте современные автономные приложения с помощью Progressive Web Apps
- RxJS Tutorial: Observables, операторы и не только
НАПИСАЛ БАЙЭрин Доэрти
Присоединяйтесь к сообществу, насчитывающему более 1,4 миллиона читателей. Бесплатное электронное письмо раз в два месяца с обзором лучших статей и советов по программированию на сайте Educative.
Обзор MVC. MVC — это шаблон дизайна, используемый для помощи… | Джозеф Спинелли
Обзор MVC. MVC — это шаблон дизайна, используемый для помощи… | Джозеф Спинелли | MediumMVC — это шаблон проектирования, используемый для создания фреймворков для приложений. Он состоит из трех разделов, которые называются Model, View и Controller. Сообщается, что MVC был изобретен Трюгве Реенскаугом в 1970-е годы. Он придумал этот дизайн как способ описать конструкции программного обеспечения с точки зрения их ответственности и эффективно реализовать их. Это популярный дизайн, который используется всеми типами языков программирования, такими как Java, C#, Ruby и PHP. В этом посте я рассмотрю каждый раздел и расскажу о том, что вы, как разработчик, должны знать и включать в каждый из них. Когда я объясняю каждую часть модели MVC, я буду связывать ее с аналогией ресторана. Думайте о шаблоне MVC как о ресторане, в котором модели являются поварами, представления — клиентами, а контроллеры — официантами.
1. Модель(повара):
Модель представляет данные и логику приложения. Модель может иметь отношения «к одному» и «ко многим» с другими моделями. Здесь данные обрабатываются и/или сохраняются. Если какие-либо данные изменяются, то модель обычно уведомляет представление, а иногда и контроллер, если для управления обновленным представлением требуется другая логика. По аналогии это будут повара. Прием еды у официанта (контролер) и приготовление еды для клиентов (вид). Таким образом, это будет брать данные из контроллера и предоставлять данные для представления.
Модель, она же Гордон Рамзи (повар)2. Представление (клиенты):
Представление — это единственная часть приложения, с которой пользователь взаимодействует напрямую. Он прикреплен к модели и, в свою очередь, отображает данные модели. Он также может обновлять модель, отправляя ей соответствующие сообщения, если это соответствует терминологии в модели. Это означает, что представление должно знать атрибуты модели, которую оно представляет. В нашей аналогии представлением будет клиент. Клиент размещает заказы и получает еду через официанта, но не имеет прямого контакта с поваром. Это будет пользователь, запрашивающий определенные данные, и представление, отображающее их для них, как бы они ни просили.
Представление, также известное как клиент3. Контроллер (официант):
Контроллер является посредником между моделями и представлениями. Он передает данные из браузера в приложение и из приложения в браузер. Он предоставляет пользователям формы и меню для ввода информации. Контроллер получает входные данные пользователей и преобразует их, а затем передает эти входные данные одному или нескольким представлениям. Он интерпретирует все действия пользователя и переходит между моделью и представлением, чтобы связать их. В ресторане официант принимает заказы от клиентов на приготовление пищи и принимает блюда от повара обратно к клиенту. Без официанта не было бы связи между клиентом и поваром. Это может быть пользователь, запрашивающий определенную веб-страницу, и контроллер, принимающий запрос пользователя и запускающий код на основе этих запросов через модели. Затем, наконец, отвечая пользователю, отображая запрошенный файл представления для отображения запрошенной веб-страницы.
Контроллер, также известный как официант Резюме MVCВажно помнить: Модель представляет данные и ничего больше не делает. Модель НЕ зависит от контроллера или представления. В заключение, правильное использование шаблона MVC может помочь вам как разработчику с легкостью поддерживать и обновлять свое приложение. Кроме того, он обеспечивает плавный и простой пользовательский опыт. Хотя это и требует времени, понимание того, почему MVC работает и как правильно ей следовать, окупится при создании будущих приложений. Я надеюсь, что этот пост был полезен, и если у вас есть какие-либо вопросы, пожалуйста, оставьте комментарий!
Спасибо!
Ресурсы:
Понимание Model-View-Controller
блог Джеффа Этвуда о программировании и человеческом факторе
blog.