Что такое mvc? шаблон проектирования model view controller (mvc) и php, часть 1

Введение

Многие начинают писать проект для работы с единственной задачей, не подразумевая, что это может вырасти в многопользовательскую систему управления, ну допустим, контентом или упаси бог, производством. И всё вроде здорово и классно, всё работает, пока не начинаешь понимать, что тот код, который написан — состоит целиком и полностью из костылей и хардкода. Код перемешанный с версткой, запросами и костылями, неподдающийся иногда даже прочтению. Возникает насущная проблема: при добавлении новых фич, приходится с этим кодом очень долго и долго возиться, вспоминая «а что же там такое написано то было?» и проклинать себя в прошлом.

Вы можеть быть даже слышали о шаблонах проектирования и даже листали эти прекрасные книги:

  • Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидесс «Приемы объектно ориентированного проектирования. Паттерны проектирования»;
  • М. Фаулер «Архитектура корпоративных программных приложений».

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

Прожженные PHP-программисты вряд ли найдут в данной статье что-то новое для себя, но их замечания и комментарии к основному тексту были бы очень кстати! Т.к. без теории практика невозможна, а без практики теория бесполезна, то сначала будет чуть-чуть теории, а потом перейдем к практике. Если вы уже знакомы с концепцией MVC, можете пропустить раздел с теорией и сразу перейти к практике.

Модель шаблона ASP.NET MVC

В шаблоне MVC платформы ASP.NET в качестве модели выступают «обыкновенные классы» C#, получающие данные из источника для формирования контента. Название класса может быть любым, но если используется Entity Framework для доступа к данных, то названия классов должны совпадать с названиями таблиц базы. Как правило, в классах происходит основная логическая работа, далее через контроллеры в представления передаются уже готовые данные. Вспомогательную часть программной обработки можно осуществлять в дополнительных классах и контроллерах, стараясь минимизировать количество программного кода в методах контроллеров.

Что такое представления в приложении ASP.NET Core MVC?

В шаблоне Model-View-Controller (MVC) представление — это компонент, который содержит логику для представления данных модели (данных модели, предоставленных ему контроллером) в качестве пользовательского интерфейса, с которым может взаимодействовать конечный пользователь. Представления в MVC — это HTML-шаблоны со встроенной разметкой Razor, которые генерируют контент, отправляемый клиенту. В наших следующих статьях мы подробно обсудим синтаксис Razor.

Где хранятся файлы представлений в приложении ASP.NET Core MVC?
В ASP.NET Core MVC представления имеют расширение «.cshtml», если язык программирования — C# с разметкой Razor. Обычно у каждого контроллера есть своя собственная папка, в которой будут храниться файлы представлений для конкретного контроллера. Папки для контроллера будут создаваться в папке Views. Необходимо помнить, что имя файла представления совпадает с именем метода действия контроллера с расширением .cshtml.

Допустим, у нас есть приложение ASP.NET Core MVC с двумя контроллерами, то есть HomeController и StudentController. HomeController создается с помощью следующих трех методов действия.

  • AboutUs()
  • ContactUs()
  • Index()

С другой стороны, StudentController создается с помощью следующих четырех методов действия.

  • Index()
  • Details()
  • Edit()
  • Delete()

Ниже приведена структура папок и файлов представлений.

Как вы можете видеть, для каждого контроллера в папке Views создается отдельная папка. Домашний контроллер представлен домашней папкой, а ученический контроллер представлен студенческой папкой внутри папки «Виды». Домашняя папка содержит представления для веб-страниц Index, AboutUs и ContactUs. Таким образом, всякий раз, когда пользователь запрашивает любую из этих веб-страниц, метод действия определяет, какое из трех представленных выше Views использовать для создания веб-страницы, и возвращать его пользователю.

Аналогичным образом папка «Студент» содержит представления для веб-страниц «Индекс», «Сведения», «Редактировать» и «Удалить». Поэтому, когда пользователь запрашивает какую-либо из этих веб-страниц, метод действия StudentController определяет, какое из представленных выше представлений использовать для создания веб-страницы и возврата к пользователю.

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

Разбор представлений на примере:
Чтобы лучше понимать, как работают представления, давайте сначала изменим HomeController, как показано ниже.

Как вы можете видеть в приведенном выше , у нас есть только один метод действия. Поскольку типом возврата метода действия является , этот метод действия будет возвращать представление. Чтобы вернуть представление, здесь мы используем метод расширения , предоставляемый базовым классом .

Теперь запустите приложение и перейдите по URL «/Home/Details», и вы увидите следующую ошибку.

Почему мы получили вышеуказанную ошибку?

Поскольку мы возвращаем представление из метода действия в , по умолчанию ASP.NET Core MVC Framework будет искать файл с именем в следующих местах:

Сначала он будет искать файл в папке , поскольку метод действия принадлежит .

Затем он будет искать в папке

И, наконец, он попытается найти этот файл в папке .

Если запрошенный файл найден в любой из указанных выше папок, то представление генерирует HTML-код и отправляет сгенерированный HTML-файл пользователю, который изначально сделал запрос. С другой стороны, если запрошенный файл не найден ни в одном из указанных мест, мы получим ошибку.

Model-View-ViewModel

Честно говоря, не знаю, используется ли данный паттерн где-то, кроме WPF и Silverlight. Здесь опять присутствуют три компоненты: модель, представление и третий компонент – дополнительная модель под названием ViewModel. Данный паттерн подходит к таким технологиям, где присутствует двухсторонний биндинг (синхронизация) элементов управления на модель, как в WPF. Отличие от MVP паттерна заключается в том, что свойство SelectedRecord, из предыдущего примера, должно находится не в представлении, а в контроллере (ViewModel), и оно должно синхронизироваться с необходимым полем в представлении. Как раз и выходит, что в этом и есть основная идея WPF. ViewModel – это некоторый суперконвертор, который преобразует данные модели в представление, в нем описываются основные свойства представления, а также логика взаимодействия с моделью. Рекомендую ознакомиться со статьей .

MVC в PHP

Особенностью при использовании MVC в PHP, является то, что существует одна точка входа в php приложение, которая, например, достигается следующим образом. Создается index.php через который будут обрабатываться все запросы, для этого создаем в папке с индексом файл .htaccess и помещаем в него такой код:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 

В предоставленном коде, первой строкой, проверяется существование запрашиваемого файла, и если его нет, то идет перенаправление на index.php, иначе даже запросы картинок сайта будут перенаправляться на индекс. Последняя строка кода преобразовывает запросы вида index.php?route=chat/index у вид index.php/chat/index. Если у вас нет возможности использовать ModRewrite в своем приложении, то вам придется делать переадресацию вручную.

PHP Модель

Данные о PHP модели содержаться в ее атрибутах и могут быть изменены только через специальные функции. Модель может содержать в себе несколько представлений. Как правило, phpмодель это класс работающий с БД, конкретнее: запись, чтение, удаление. Естественно чтение информации с БД может быть реализовано несколькими представлениями (функциями). Как пример модель статей на сайте: можно получить конкретную статью из БД, список последних, популярных, какой-то категории… это все представления модели. Для наглядности ниже предоставлен пример php модели.

<?php function methodName()
{
$link = mysql_connect(’localhost’, ‘mysql_user’, ‘mysql_password’);
if (!$link) {
die(’Could not connect: ‘ . mysql_error());
}
echo ‘Connected successfully’;
mysql_close($link);
$query_results= mysql_query(’select * from searchNames order by firstname desc’);
$data = array();
while ($row = mysql_fetch_objects($query_results)) {
$data[] = $row;
}
return $data;
}
?>

PHP контролер (Поведение)

PHP контролеры получают запросы пользователей, которые мы направляли через index.php, и в соответствии с ними, корректируют работу модели. Правильнее сказать контролируют работу php приложения.

<?php $data= methodName();
display_template(’data.tpl’);
?>

PHP Представление

Представление отслеживает изменение в модели и создает или меняет интерфейс php приложения.

<?php echo $row->lastname?>

<?php } ?>

Как работает данный PHP MVC шаблон?

При обращении пользователем по нужному url выбирается соответственный контролер, который обращается к представлению и модели, и выводится информация. Другими словами контролер в mvc есть связующим звеном модели и представления.

Преимущества MVC шаблона при создании PHP приложения

Как упоминалось выше это, прежде всего дифференциация разработчиков php сайта на отделы. Также увеличивается скорость работы php приложения, если создается крупный проект. Ну и то, что касается непосредственно самого php разработчика, это правильная структуризация php кода (все на своих местах, так легче для понимания).

MVC пример

Особо не будем зацикливаться на примере работы MVC, так как уже имеется Добавлю лишь еще пару схем для более глубокого понимания.

Еще одна схема работы MVC шаблона на PHP, она более чем доступна для понимания.

Модель-представление (model-view)

Шаблон MVC направлен на отделение данных и логики (модели) от интерфейса (представления) программы. Так, например, при разработке игры «Тетрис» к модели могут относится массив с фигурами и логика игры, а представление отвечает за отображение этого массива на экране.Такое разделение соответствует принципу единой обязанности (SRP) , соблюдение которого обеспечивает:

  • лучшую тестируемость кода, т.к. вы можете писать unit-тесты к модели и виду независимо друг от друга, что позволит более точно выявлять место с ошибкой при провале какого-либо из тестов ;
  • ослабление зависимостей между видом и представлением, а значит более высокую гибкость. В любой момент заменить одно представление на другое, т.к. теперь модель не зависит от представления. В частности замена представления может быть необходима при переносе программы на мобильную платформу с другим пользовательским интерфейсом;
  • снижение сложности проекта также является следствием ослабления зависимостей. Разрабатывать отдельные части можно дать программистам с более низкой квалификацией.

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

Модель и представление игры Тетрис

Это здорово, но откуда представление узнает, что в модели какие-либо данные изменились? — при использовании MVC для этого используется шаблон проектирования publish-subscribe.

Понятие реквизита объекта и узла. Реквизиты ссылочного типа или простого

Подсистема в процессе расчета зависимостей оперирует узлами и связями. В результате расчета зависимостей получаются реквизиты. Реквизиты могут быть ссылочного типа или простого. Для второго случая для расчета значения реквизита связи не используются.

Узел указывает на реквизит в метаданных. Для реквизитов коллекции используется описание узла без указания на конкретную строку. Под реквизитом понимается путь до данных объекта. Если реквизит является частью коллекции, то к описанию пути к данным добавляется указание идентификатора строки. В последнем случае идентификатором строки могут быть как идентификатор строки на форме, так и номер строки, если в качестве контекста выступает сам объект.

Реквизит может быть ссылочного типа или простого. Параметры связей используются для ограничения выбора значения реквизитов ссылочного типа. Для реквизитов простого типа вычисление значения реквизита по связям не используется.

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

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

Веб-API

Помимо того, что ASP.NET Core MV прекрасно подходит для создания веб-сайтов, эта платформа располагает мощной поддержкой для построения веб-API. Создавайте службы, доступные для широкого круга клиентов, включая браузеры и мобильные устройства.

Платформа поддерживает согласования содержимого HTTP со встроенной поддержкой для форматирования данных в виде JSON или XML. Пишите пользовательские модули форматирования для добавления поддержки собственных форматов.

Используйте функции создания ссылок для поддержки гипермедиа. Легко включайте поддержку общего доступа к ресурсам независимо от источника (CORS) для совместного использования веб-API в нескольких веб-приложениях.

Types of Cocoa Controller Objects

sketches the abstract outline of a controller object, but in practice the picture is far more complex. In Cocoa there are two general kinds of controller objects: mediating controllers and coordinating controllers. Each kind of controller object is associated with a different set of classes and each provides a different range of behaviors.

A mediating controller is typically an object that inherits from the class. Mediating controller objects are used in the Cocoa bindings technology. They facilitate—or mediate—the flow of data between view objects and model objects.

Mediating controllers are typically ready-made objects that you drag from the Interface Builder library. You can configure these objects to establish the bindings between properties of view objects and properties of the controller object, and then between those controller properties and specific properties of a model object. As a result, when users change a value displayed in a view object, the new value is automatically communicated to a model object for storage—via the mediating controller; and when a property of a model changes its value, that change is communicated to a view for display. The abstract class and its concrete subclasses—, , , and —provide supporting features such as the ability to commit and discard changes and the management of selections and placeholder values.

A coordinating controller is typically an or object (available only in AppKit), or an instance of a custom subclass of . Its role in an application is to oversee—or coordinate—the functioning of the entire application or of part of the application, such as the objects unarchived from a nib file. A coordinating controller provides services such as:

  • Responding to delegation messages and observing notifications

  • Responding to action messages

  • Managing the life cycle of owned objects (for example, releasing them at the proper time)

  • Establishing connections between objects and performing other set-up tasks

and are classes that are part of the Cocoa architecture for document-based applications. Instances of these classes provide default implementations for several of the services listed above, and you can create subclasses of them to implement more application-specific behavior. You can even use objects to manage windows in an application that is not based on the document architecture.

A coordinating controller frequently owns the objects archived in a nib file. As File’s Owner, the coordinating controller is external to the objects in the nib file and manages those objects. These owned objects include mediating controllers as well as window objects and view objects. See for more on coordinating controllers as File’s Owner.

Instances of custom subclasses can be entirely suitable as coordinating controllers. These kinds of controller objects combine both mediating and coordinating functions. For their mediating behavior, they make use of mechanisms such as target-action, outlets, delegation, and notifications to facilitate the movement of data between view objects and model objects. They tend to contain a lot of glue code and, because that code is exclusively application-specific, they are the least reusable kind of object in an application.

Паттерн Publish-Subscribe (Издатель-Подписчик)

Если один или несколько объектов в Вашем проекте должны отслеживать изменения другого объекта — гибким решением будет применение шаблона проектирования Publish-Subscribe.

При изменении своего состояния, издатель оповещает всех своих подписчиков, путем вызова у них какой-либо функции, инициализирующей обновление подписчика. При этом, издатель должен предоставлять функции для добавления и удаления подписчиков. Выделение таких функций в виде интерфейсов (базовых классов подписчика и издателя) позволяет ослабить зависимости в соответствии с принципом инверсии зависимостей (Dependency Inversion Principle) — Издатель будет зависеть лишь от интерфейса подписчика, но не от его конкретного типа .

В качестве примера, рассмотрим табличные процессоры (MS Excel и аналоги), позволяющие строить разные виды графиков и диаграмм по данным таблицы. При изменении данных в таблице, графики в таких системах могут автоматически перестраиваться. Для этого таблица рассылает уведомление об изменении данных всем, кто на нее подпишется.

Шаблон Publish-Subscribe. Пример использования

На диаграмме показаны основные элементы шаблона:

  • AbstractSubscriber, задает интерфейс подписчиков;
  • EyeChart, один из реальных подписчиков (легко могут быть добавлены другие виды диаграмм). Хранит ссылку на издателя, при помощи которой получает его обновленное состояние после получения сигнала об обновлении данных;
  • AbstractPublisher, задает интерфейс издателей. Может реализовывать этот интерфейс (не являться абстрактным), т.к. все издатели должны одинаково добавлять/удалять подписчика и уведомлять их об обновлении;
  • SpreadSheet, таблица с данными, уведомляющая подписчиков об изменении своих данных.

В результате применения шаблона:

  • ослабляется зависимость издателя от подписчика. Остается зависимость лишь от абстрактного класса, что позволяет без модификации кода издателя добавлять новые типы подписчиков;
  • появляется возможность добавлять и удалять подписчиков во время выполнения программы. Издатель не располагает информацией не только о конкретных типах Подписчиков, но и об их количестве. Так, например, во многих играх наряду с картой, отображающей состояние игрового мира присутствует мини-карта. Обе карты являются подписчиками, а игровой мир — издателем, при этом для отключения мини-карты достаточно удалить соответствующий объект и снять его с подписки.

Два слова об MVC

Применение паттерна MVC заключается в разделении собственно данных, их отображения и обработки действий пользователя по трем компонентам.

Модель (Model)
Собственно данные, методы для работы с данными, изменения и обновления данных.
Представление/Вид (View)
Отображение данных, оформление и другие аспекты презентации модели
Контроллер (Controller)
Реагирует на действия пользователя, интерпретирует данные, введенные пользователем, и информирует модель и производит необходимые манипуляции с моделью и видом.

Между компонентами есть взаимодействия, изображенные стрелочками на рисунке (один из устоявшихся вариантов MVC).

Главный тезис статьи можно сформулировать так:

Дальнейшая часть статьи — обоснование с примерами, почему именно так, а не иначе, и почему устоявшаяся практика MVC для javascript-интерфейсов работает плохо.

Архитектура “модель-вид-контроллер” (Model-View-Controller, MVC)

Самая популярная архитектура ПО на сегодняшний день  —  “модель-вид-контроллер”, или сокращенно MVC.

MVC делит любое крупное приложение на три части:

  • Модель.
  • Вид (или, по-другому, представление).
  • Контроллер.

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

Модель

Модель содержит всю логику данных, с которой работает пользователь: схемы и интерфейсы проекта, базы данных и их поля.

Например, объект клиента будет извлекать информацию о клиенте из базы данных, манипулировать записями в БД и обновлять их или пользоваться полученной информацией для визуализации данных.

Вид

Вид содержит пользовательский интерфейс и представление приложения.

Например, представление клиента будет включать все компоненты пользовательского интерфейса: текстовые поля, раскрывающиеся списки и другие элементы, с которыми взаимодействует пользователь.

Контроллер

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

Например, контроллер клиента будет обрабатывать все взаимодействия и входные данные из представления клиента и обновлять базу данных с использованием модели клиента. Тот же контроллер будет задействован для просмотра данных о клиентах.

Вот схема, которая поможет визуализировать архитектуру MVC и принцип ее работы:

Блок-схема MVC

Model-View-Controller

MVC состоит из трех компонент: View (представление, пользовательский интерфейс), Model (модель, ваша бизнес логика) и Controller (контроллер, содержит логику на изменение модели при определенных действиях пользователя, реализует Use Case). Основная идея этого паттерна в том, что и контроллер и представление зависят от модели, но модель никак не зависит от этих двух компонент. Это как раз и позволяет разрабатывать и тестировать модель, ничего не зная о представлениях и контроллерах. В идеале контроллер так же ничего не должен знать о представлении (хотя на практике это не всегда так), и в идеале для одного представления можно переключать контроллеры, а также один и тот же контроллер можно использовать для разных представлений (так, например, контроллер может зависеть от пользователя, который вошел в систему). Пользователь видит представление, на нем же производит какие-то действия, эти действия представление перенаправляет контроллеру и подписывается на изменение данной модели, контроллер в свою очередь производит определенные действия над моделью данных, представление получает последнее состояние модели и отображает ее пользователю.

Реализация в ASP.NET будет выглядит следующим образом (пример взят с MSDN ). Представление – это обычная aspx разметка:

Модель – отдельный класс, у которого есть методы получения данных (модель в реализациях часто включает в себя так же и Data Access Level):

Пример модели не самый удачный в данном случае, но все-таки не всегда бывает необходимость иметь действительно описанную бизнес модель в классах, иногда хватает и работы с DataSet’ами. Самое интересное, это реализация контроллера, по сути это code behind aspx страницы.

Данный подход даст нам возможность с легкостью написать тесты для модели, но не для контроллера (конечно же, все возможно, но придется постараться).

Есть ли жизнь без MVC?

Есть. Не используйте MVC-шаблон для веба в реализации от популярных фреймворков. Изобретайте своё, фантазируйте. Помните, что «своё» не «пахнет».

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

Вот так может выглядеть action без MVC:

Пример вида:

А вот пример разработки кабинета без MVC:

Your browser does not support HTML5 video.

Сделать подобный интерфейсе на «обычном» фреймворке, на мой взгляд, очень проблематично. Это хорошо, когда у вас много программистов, включая фронтэндеров, но этот проект я делал один при сильно ограниченном лимите часов разработки. Если бы я попытался идти по пути, например, Yii 2, то только представьте сколько форм, моделей, контроллеров пришлось бы создавать и как-то связывать вместе.

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

Основная цель следования принципам MVC — отделить реализацию бизнес-логики приложения (модели) от ее визуализации (вида). Такое разделение повысит возможность повторного использования кода. Польза применения MVC наиболее наглядна в случаях, когда пользователю нужно предоставлять одни и те же данные в разных формах. Например, в виде таблицы, графика или диаграммы (используя различные виды). При этом, не затрагивая реализацию видов, можно изменить реакции на действия пользователя (нажатие мышью на кнопке, ввод данных). Если следовать принципам MVC, можно упростить написание программ, повысить читаемость кода, сделать легче расширение и поддержку системы в будущем.

Хорошая практика MVC по версии фреймворков

Руководство Yii 2 гласит: «Yii приложения организованы согласно шаблону проектирования модель-представление-контроллер (MVC)». На практике там действительно есть папки, которые называются «модели», «виды», «контроллеры». Но, если копнуть глубже, то, вида может и не быть, модель тоже опциональна. Зато всегда есть контроллер, действие и много чего ещё.

Остальные фреймворки, плюс-минус, организованны по тому же принципу: на основании URL определяется контроллер (controller) и функция (action или действие), которая затем вызывается. В качестве аргументов в функцию может передаваться объект запроса или какие-то части URL. В теле функции можно обработать входные данные (через модели или абы как) и подключить вид. Некоторые фреймворки подключают вид сами, более порядочные ждут, когда вид вызовут.

Рассмотрим примеры контроллеров популярных фреймворков:

Разницы между этими контроллерами, на мой взгляд, практически нет. Все они классы, у всех есть функция-действие и все они возвращают «вид» (zf3 делает это неявно). По-большому счёту нет никакой разницы, какой MVC вы будете использовать, все они построены по одному шаблону, который к MVC имеет призрачное отношение.

модель презентации

Еще один шаблон, на который следует обратить внимание, — это шаблон модели презентации. В этом шаблоне нет ведущего

Вместо этого представление привязывается непосредственно к модели презентации. Модель представления-это модель, созданная специально для представления. Это означает, что эта модель может выставлять свойства, которые никогда не будут помещены в модель домена, так как это было бы нарушением separation-of-concerns. В этом случае модель представления привязывается к модели домена и может подписываться на события, поступающие из этой модели. Затем представление подписывается на события, поступающие из модели представления, и обновляет себя соответствующим образом. Модель представления может предоставлять команды, которые представление использует для вызова действий. Преимущество этого подхода заключается в том, что вы можете по существу полностью удалить код, так как PM полностью инкапсулирует все поведение для представления. Этот шаблон является очень сильным кандидатом для использования в WPF приложениях и также называется Model-View-ViewModel .

Существует статья MSDN о модели представления и раздел в руководстве по составному применению для WPF (бывшая Призма) о разделенных шаблонах представления

Проклятье MVC

Когда мне предлагают использовать тот или иной «суперклёвый» фреймворк (в основном это MVC-фреймворки), я сразу уточняю, а куда там можно запихать две тонны и маленькую тележку говнокода. Я пока не видел крупных проектов, в которых был бы только чистый код.

Если контроллер сделан в виде класса, то он должен подчиняться правилам написания классов (принципы SOLID). Это значит, что туда нельзя запихать даже маленькую тележку, не говоря уже о двух тоннах.

На практике люди пихают в свои контроллеры даже не тонны, а мегатонны всего, что только можно и нельзя. По какому-то неведомому принципу контроллер = справочник. Назвался , будь добр уметь создавать, обновлять и удалять альбомы. Это хорошо, когда справочник простой и понятный, а что делать, когда нужен справочник-матрёшка? Например, справочник исполнителей в альбоме. А у исполнителей есть свои альбомы, да ещё и с обложками и историей покупок.

Когда задача выходит за рамки документации, то начинается полёт буйной фантазии разработчиков. Обычно такие полёты и порождают монстров в тысячи строк. Это, увы, не редкость в современном веб-MVC.

Некоторые оправдывают использование ООП для контроллеров возможностью писать юнит-тесты и повторно использовать отдельные методы класса. Но в своей практике я не видел ни того, ни другого. А вот тонны говнокода в контроллерах видел. Куда ж его ещё девать? Но это, как мы знаем, фу-фу-фу и так делать нельзя. А куда тогда девать ценнейшее удобрение умственной деятельности сильных мира сего? В модели? Так ведь они тоже классы и подчиняются тем же правилам. Дробить большую какашку на много маленьких и делать вид, что это хэлперы? Наверное можно, но обилие лишних классов само по себе превращает проект в сплошной кусок сами-знаете-чего.

Преимущества архитектуры

Архитектура MVC предлагает множество преимуществ для программиста при разработке приложений, которые включают в себя:

  • Несколько разработчиков могут работать с тремя слоями (Модель, Вид и Контроллер) одновременно.
  • Обеспечивает улучшенную масштабируемость, которая дополняет способность приложения расти.
  • Поскольку компоненты имеют низкую зависимость друг от друга, их легко поддерживать.
  • Модель может быть повторно использована несколькими представлениями, что обеспечивает возможность повторного использования кода.
  • Принятие MVC делает приложение более выразительным и простым для понимания.
  • Расширение и тестирование приложения становится легким.

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

Продолжаем делить приложение на модули, но уже на более низком уровне иерархии. На этом шаге пользовательский интерфейс (который был выделен в отдельный модуль на шаге 1) делится на вид и контроллер. Сложно провести строгую черту между видом и контроллером. Если говорить о том, что вид — это то, что видит пользователь, а контроллер — это механизм, благодаря которому пользователь может взаимодействовать с системой, можно обнаружить некоторое противоречие. Элементы управления, например, кнопки на веб-странице или виртуальная клавиатура на экране телефона, это по сути часть контроллера. Но они так же видны пользователю, как и любая часть вида. Здесь скорее речь идет о функциональном разделении. Основная задача пользовательского интерфейса — обеспечить взаимодействие пользователя с системой. Это означает, что у интерфейса всего 2 функции:

  • выводить и удобно отображать пользователю информацию о системе;
  • вводить данные и команды пользователя в систему (передавать их системе);

Данные функции и определяют то, как нужно делить интерфейс на модули. В итоге, архитектура системы выглядит так: Итак, у нас появилось приложение из трех модулей, которые называются Модель, Вид и Контроллер. Резюмируем:

  1. Следуя принципам MVC, систему нужно разделять на модули.
  2. Самым важным и независимым модулем должна быть модель.
  3. Модель — ядро системы. Нужна возможность разрабатывать и тестировать ее независимо от интерфейса.
  4. Для этого на первом шаге сегрегации системы нужно разделить ее на модель и интерфейс.
  5. Далее, с помощью шаблона Наблюдатель, укрепляем модель в ее независимости и получаем синхронизацию пользовательских интерфейсов.
  6. Третьим шагом делим интерфейс на контроллер и вид.
  7. Все, что на ввод информации от пользователя в систему — это в контроллер.
  8. Все что на вывод информации от системы к пользователю — это в вид.

Осталось обсудить еще одну важную вещь и можно пить какао.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: