Содержание

Что такое MVC: рассказываем простыми словами

Современные сайты интерактивные и динамичные, то есть они реагируют на действия пользователя, обрабатывают его запросы и выдают результат. Так работают онлайн-сервисы, например, интернет-банкинг или онлайн-кинотеатр. Для создания интерактивных и динамичных сайтов обычно используется архитектурный паттерн MVC. В этой статье простыми словами объясняется суть этой модели.

  • Что такое модель MVC: теория
  • Разбираем MVC на примере магазина сэндвичей
  • Паттерн MVC в реальной веб-разработке: простые примеры
    • Контроллер
    • Модель
    • Представление
  • Заключение

Что такое модель MVC: теория

Статическая страница на HTML не умеет реагировать на действия пользователя. Для двухстороннего взаимодействия нужны динамические веб-страницы. MVC — ключ к пониманию разработки динамических веб-приложений, поэтому разработчику нужно знать эту модель.

MVC расшифровывается как модель-представление-контроллер (от англ.

model-view-controller). Это способ организации кода, который предполагает выделение блоков, отвечающих за решение разных задач. Один блок отвечает за данные приложения, другой отвечает за внешний вид, а третий контролирует работу приложения. Компоненты MVC:

  • Модель — этот компонент отвечает за данные, а также определяет структуру приложения. Например, если вы создаете To-Do приложение, код компонента model будет определять список задач и отдельные задачи.
  • Представление — этот компонент отвечает за взаимодействие с пользователем. То есть код компонента view определяет внешний вид приложения и способы его использования.
  • Контроллер — этот компонент отвечает за связь между model и view. Код компонента controller определяет, как сайт реагирует на действия пользователя. По сути, это мозг MVC-приложения.

Чтобы лучше понять теоретическую информацию, используем абстрактное описание.

Разбираем MVC на примере магазина сэндвичей

Мы уже рассматривали работу с вложенными коллбэками на примере приготовления гамбургеров. Продолжаем традицию: разберем паттерн MVC на примере магазина сэндвичей.

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

Продавец или бармен с полуслова понимает вас. Он поворачивается в сторону кухни и говорит поварам, чтобы они приготовили сэндвич с индейкой.

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

Покупку бутерброда можно описать через MVC:

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

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

Это представление или view.

Справка: иногда модель 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?

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 шагов:

Шаги:

  1. Пользователь кликает по ссылке «рекомендованы» и браузер отправляет запрос на, допустим, /books/recommendations.
  2. Контроллер проверяет запрос: пользователь должен быть залогинен. Или у нас должны быть подборки книг для незалогиненных пользователей. Затем контроллер обращается к модели и просит ее отдать список книг, рекомендованных пользователю N.
  3. Модель обращается в базу данных, достает оттуда информацию о книгах: популярные сейчас книги, книги, купленные пользователем, книги, купленные его друзьями, книги из его wish list. На основе этих данных модель строит список из 10 рекомендованных книг и возвращает их контроллеру.
  4. Контроллер получает список рекомендованных книг и смотрит на него. На этом этапе контроллер принимает решения! Если книг мало или список вообще пустой, то он запрашивает список книг для незалогиненного пользователя. Если сейчас идет акция, то контроллер может добавить в список акционные книги.
  5. Контроллер определяется с тем, какую страницу показать пользователю. Это может быть страница с ошибкой, страница со списком книг, страница поздравление о том, что пользователь стал миллионным посетителем.
  6. Сервер отдает клиенту страницу (view), выбранную контроллером. Она заполняется нужными данными (имя пользователя, список книг) и уходит к клиенту.
  7. Клиент получает страницу и отображает ее пользователю.

В чем преимущества такого подхода?

Самое очевидное преимущество, которое мы получаем от использования концепции 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

Три важных компонента 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?