Введение

Шаблон проектирования программного обеспечения

Модель — представление — контроллер (MVC) — это шаблон проектирования программного обеспечения, широко используемый для разработки пользовательских интерфейсов, который разделяет связанную логику программы на три взаимосвязанных элемента. Эти элементы:
модель — внутреннее представление информации;
представление — интерфейс, который отображает информацию и принимает ввод от пользователя;
контроллер — программное обеспечение, связывающее модель и представление. Изначально использовавшийся для настольных графических пользовательских интерфейсов (GUI), этот шаблон стал популярным при разработке веб-приложений. Многие популярные языки программирования имеют MVC-фреймворки, облегчающие реализацию этого шаблона.

История

Один из основополагающих принципов в раннем развитии графических пользовательских интерфейсов, MVC стал одним из первых подходов к описанию и реализации программных конструкций с точки зрения их ответственности. Тригве Реенскауг создал MVC, работая над Smalltalk 79 в качестве приглашенного ученого в Исследовательском центре Xerox Palo Alto (PARC) в конце 1970-х годов. Ему был нужен шаблон, который можно было бы использовать для структурирования любой программы, где пользователи взаимодействуют с большим и сложным набором данных. Изначально его дизайн состоял из четырех частей: модель, представление, сущность и редактор. После обсуждения с другими разработчиками Smalltalk он и остальная группа пришли к согласию об использовании модели, представления и контроллера. В 1988 году в статье в The Journal of Object Technology (JOT) два бывших сотрудника PARC представили MVC как общую "парадигму и методологию программирования" для разработчиков Smalltalk 80. Однако их схема отличалась как от схемы, предложенной Reenskaug и другими, так и от той, что была представлена в справочных книгах по Smalltalk 80. Они определили представление как охватывающее любые вопросы, связанные с графикой, а контроллер – как более абстрактный, обычно невидимый объект, который получает ввод от пользователя и взаимодействует с одним или несколькими представлениями и только с одной моделью. Впоследствии шаблон MVC развивался, порождая такие варианты, как иерархический MVC (HMVC), MVC-адаптер (MVA), MVC-представитель (MVP), MVC-модель-представление-ViewModel (MVVM) и другие, которые адаптировали MVC к различным контекстам. Использование шаблона MVC в веб-приложениях возросло после появления WebObjects от NeXT в 1996 году, который изначально был написан на Objective-C (в значительной степени заимствовавшем у Smalltalk) и помог обеспечить соблюдение принципов MVC. Позже MVC стал популярен среди разработчиков Java, когда WebObjects был портирован на Java. Последующие фреймворки для Java, такие как Spring (выпущенный в октябре 2002 года), продолжили тесную связь между Java и MVC. В 2003 году Мартин Фаулер опубликовал книгу Patterns of Enterprise Application Architecture, в которой представил MVC как шаблон, в котором "входной контроллер" получает запрос, отправляет соответствующие сообщения объекту модели, получает ответ от объекта модели и передает ответ соответствующему представлению для отображения. Это близко к подходу, используемому в веб-фреймворке Ruby on Rails (август 2004 года), в котором клиент отправляет запросы на сервер через представление в браузере, эти запросы обрабатываются контроллером на сервере, а контроллер взаимодействует с соответствующими объектами модели. Фреймворк Django (июль 2005 года, для Python) предложил аналогичный подход "модель-шаблон-представление" (MTV), в котором представление извлекает данные из моделей и передает их шаблонам для отображения. И Rails, и Django дебютировали с акцентом на быструю разработку, что повысило популярность MVC за пределами традиционной корпоративной среды, где он давно был популярен.

Модель

Центральный компонент шаблона. Это динамическая структура данных приложения, независимая от пользовательского интерфейса. Она непосредственно управляет данными, логикой и правилами приложения. В Smalltalk 80 разработка типа модели полностью лежит на программисте. В WebObjects, Rails и Django тип модели обычно представляет собой таблицу в базе данных приложения.

Вид

Любое представление информации, такое как график, диаграмма или таблица. Возможно несколько вариантов отображения одной и той же информации, например, столбчатая диаграмма для руководства и табличное представление для бухгалтеров. В Smalltalk 80 вид – это просто визуальное представление модели и не обрабатывает ввод пользователя. В WebObjects вид представляет собой полноценный элемент пользовательского интерфейса, такой как меню или кнопка, и получает ввод от пользователя. Однако как в Smalltalk 80, так и в WebObjects, виды предназначены для общего использования и компоновки. В Rails и Django роль вида выполняют HTML-шаблоны, поэтому в их схеме вид определяет пользовательский интерфейс в браузере, а не представляет непосредственно виджет пользовательского интерфейса. (Django предпочитает называть такие объекты "шаблонами" с учетом этого.) Этот подход уделяет относительно меньше внимания небольшим, компонуемым видам; типичный вид Rails имеет соответствие один к одному с действием контроллера. В Smalltalk 80 вид взаимодействует как с моделью, так и с контроллером, в то время как в WebObjects вид взаимодействует только с контроллером, который затем взаимодействует с моделью. В Rails и Django вид/шаблон используется контроллером/видом при подготовке ответа клиенту.

Контроллер

Принимает входные данные и преобразует их в команды для модели или представления. Контроллер Smalltalk 80 обрабатывает события пользовательского ввода, такие как нажатия кнопок или движения мыши. В любой момент времени каждый контроллер связан с одним представлением и одной моделью, хотя один объект модели может взаимодействовать со многими различными контроллерами. Только один контроллер, "активный" контроллер, получает пользовательский ввод в любой момент времени; глобальный объект – менеджер окон – отвечает за установку текущего активного контроллера. Если пользовательский ввод требует изменения модели, контроллер сигнализирует модели об изменении, но затем модель сама отвечает за уведомление своих представлений об обновлении. В WebObjects представления обрабатывают пользовательский ввод, а контроллер выступает посредником между представлениями и моделями. Может быть только один контроллер на приложение или один контроллер на окно. Большая часть прикладной логики содержится в контроллере. В Rails запросы от клиента, поступающие на серверное приложение, отправляются в "маршрутизатор", который сопоставляет запрос с конкретным методом конкретного контроллера. Внутри этого метода контроллер взаимодействует с данными запроса и соответствующими объектами модели, а затем формирует ответ, используя представление. Как правило, каждое представление имеет связанный контроллер; например, если приложение имеет представление клиентов, то обычно у него есть и контроллер Клиентов. Однако разработчики могут создавать другие типы контроллеров по своему усмотрению. В Django объект, выполняющий эту роль, называется "представлением" (view), а не контроллером.

Мотивация

Как писал Алан Кей в 2003 году, изначальной целью разработки MVC было обеспечение возможности создания графического интерфейса для любого объекта. Это было подробно описано в книге Ричарда Паусона "Naked Objects" ("Обнаженные объекты").

Использование в веб-приложениях

Хотя MVC изначально разрабатывался для настольных компьютеров, он получил широкое распространение в качестве архитектурного подхода для веб-приложений на основных языках программирования. Было создано множество веб-фреймворков, реализующих этот подход. Эти программные фреймворки различаются в своих интерпретациях, в основном в том, как обязанности MVC распределяются между клиентом и сервером. Первые фреймворки MVC использовали подход с тонким клиентом, при котором почти вся логика модели, представления и контроллера размещалась на сервере. В этом подходе клиент отправляет запросы по гиперссылкам или отправляет формы контроллеру, а затем получает полностью обновленную веб-страницу (или другой документ) от представления; модель полностью находится на сервере. Более поздние фреймворки позволили компонентам MVC частично выполняться на стороне клиента, используя Ajax для синхронизации данных.