Главная страница   /   3.2. Понимание MVC паттерна (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

3.2. Понимание MVC паттерна

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

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

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

Модели также определяются тем, за что они не несут ответственность: модели не занимаются UI и обработкой запросов – это обязанности представлений и контроллеров. Представления содержат логику, необходимую для отображения элементов модели пользователю, и больше ничего. Они не имеют прямого понимания модели и никоим образом напрямую не сообщаются с моделью. Контроллеры являются мостом между представлениями и моделью: запросы приходят от клиента и обслуживаются контроллером, который выбирает соответствующее представление для показа пользователю и, при необходимости, соответствующие действия, которые нужно выполнить с моделью.

Каждый элемент MVC архитектуры является четко определенным и автономным – это называется разделением понятий. Логика, которая манипулирует данными в модели, содержится только в модели; логика, которая отображает данные, находится только в представлении, а код, который обрабатывает запросы пользователей и вводные данные, содержится только в контроллере. С четким разделением обязанностей между каждой из частей ваше приложение будет легче поддерживать и расширять, независимо от того, насколько большим оно будет становиться.

Понимание доменной модели

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

Затем мы создаем программное представление домена – доменную модель. Для наших целей доменная модель представляет собой набор типов C# (классы, структуры и т.д.), известных под общим названием доменные типы. Операции из домена представлены методами, определенными в доменных типах, а доменные правила выражаются в логике внутри этих методов, или, как мы видели в предыдущей главе, в применении C# атрибутов к методам. Когда мы создаем экземпляр доменного типа, чтобы представить определенный фрагмент данных, мы создаем доменный объект. Доменные модели, как правило, постоянны – есть много разных способов достижения этого, но реляционные базы данных остаются наиболее распространенным выбором.

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

Совет

Распространенный способ обеспечения разделения доменной модели и остальной части ASP.NET MVC приложения заключается в том, чтобы поместить модель в отдельную сборку C#. Таким образом, вы можете создать ссылки на доменную модели из других частей приложения, но нужно убедиться, что в обратном направлении ссылок нет. Это особенно полезно в крупномасштабных проектах. Мы будем использовать такой подход в примере, который мы начнем строить в главе 7.

ASP.NET реализация MVC

В MVC контроллеры являются C# классами, как правило, производными от класса System.Web.Mvc.Controller. Каждый открытый (public) метод в классе, производный от Controller, называется методом действия, который связан с настраиваемым URL через систему маршрутизации (роутингом) ASP.NET. При отправке запроса на URL, связанный с методом действия, исполняются выражения в классе контроллера для того, чтобы выполнить некоторые операции над доменной моделью, а затем выбрать представление для отображения клиенту. На рисунке 3-1 показано взаимодействие между контроллером, моделью и представлением.

Рисунок 3-1: Взаимодействие основных компонентов в MVC приложении

ASP.NET MVC Framework обеспечивает поддержку выбора движков представления. Более ранние версии MVC использовали стандартный ASP.NET движок представления, который обрабатывал ASPX страницы с помощью модернизированной версии синтаксиса разметки Web Forms. MVC 3 ввел движок представления Razor, который был усовершенствован в MVC 4 и который использует полностью другой синтаксис (описанный в главе 5). Visual Studio обеспечивает поддержку IntelliSense для обоих движков представления, что сильно упрощает работу с данными представления, отправленными контроллером.

ASP.NET MVC не применяет никаких ограничений на реализацию вашей доменной модели. Вы можете создать модель с помощью обычных C# объектов и осуществлять хранение при помощи любой из баз данных, объектно-реляционных фреймворков или других инструментов хранения данных, поддерживаемых .NET. Visual Studio создает папку /Models в рамках шаблона MVC проекта. Это подходит для простых проектов, но в более сложных приложениях, как правило, доменные модели определяются в отдельный проект Visual Studio. Мы обсудим реализацию доменной модели далее в этой главе.

Сравнение MVC с другими паттернами

MVC – это не единственный архитектурный паттерн программного обеспечения, конечно, есть много других, и некоторые из них (или по крайней мере были) чрезвычайно популярны. Мы можем многое узнать об MVC, рассмотрев другие паттерны. В следующих разделах мы кратко опишем различные подходы к структурированию приложения и сопоставим их с MVC. Некоторые из паттернов являются близкими вариациями на тему MVC, в то время как другие совершенно отличаются.

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

Паттерн Smart UI

Один из наиболее распространенных паттернов известен как smart UI. Большинство программистов в какой-то момент своей карьеры создавали smart UI приложения, мы, конечно же, тоже. Если вы использовали Windows Forms и ASP.NET Web Forms, то и вы тоже.

Чтобы создать smart UI приложение, разработчики выстраивают пользовательский интерфейс, обычно путем перетаскивания набора компонентов или элементов управления на дизайнерскую поверхность. Элементы управления сообщают о взаимодействии с пользователем, представляя события для нажатия кнопок, нажатия клавиш, движения мыши и так далее. Разработчик добавляет код в ответ на эти события в серии обработчиков событий – небольших блоков кода, которые вызываются, когда происходит определенное событие для определенного компонента. И тут мы заканчиваем с монолитным приложением, как показано на рисунке 3-2 – код, который обрабатывает пользовательский интерфейс и логика смешиваются вместе, понятия вообще не разделены. Код, который определяет допустимые значения для вводимых данных, запросов данных или изменяет учетную запись пользователя, делится на маленькие кусочки, соединенные вместе по порядку, в котором ожидаются события.

Рисунок 3-2: Smart UI паттерн

Самым большим недостатком этой конструкции является то, что ее трудно поддерживать и расширять: смешивание доменной модели и кода бизнес логики с кодом пользовательского интерфейса приводит к дублированию, где тот же фрагмент бизнес логики копируется и вставляется для поддержки вновь добавленного компонента. Поиск всех дублирующих частей и внесение правок может быть трудным, а в сложном smart UI приложении иногда почти невозможно добавить новую функцию, не ломая существующую. Тестирование smart UI приложений также может быть трудным, единственный способ – это имитации взаимодействий с пользователем, которая далека от идеала и не обеспечивает основу для полного тестирования.

В мире MVC Smart UI часто называют анти-паттерном, которого следует избегать любой ценой. Эта антипатия возникла, по крайней мере, частично потому, что люди пришли к MVC в поисках альтернативы, проведя часть своей карьеры, пытаясь развивать и поддерживать Smart UI приложения. Это, безусловно, относится и к нам, и мы оба несем в себе следы этих долгих лет, но мы не отвергаем smart UI паттерн полностью. Не все гладко в smart UI паттерне, но есть и положительные аспекты в таком подходе. Smart UI приложения быстро и легко разрабатывать: создатели инструментария приложили много усилий для того, чтобы разработка была приятной, и даже самый неопытный программист может создать нечто профессионально выглядящее и достаточно функциональное в течение нескольких часов.

Самая большая слабая сторона Smart UI приложений – сопровождение и поддержка – не видна при разработке небольших приложений. Если вы создаете простой инструмент для небольшой аудитории, то Smart UI приложение может быть идеальным решением. Дополнительная сложность MVC приложений просто не оправдана.

Наконец, Smart UI идеально подходит для создания прототипов пользовательского интерфейса, эти инструменты конструирования действительно хороши. Если вы сидите с клиентом и хотите понять требования к интерфейсу, инструменты Smart UI могут быть быстрым и отзывчивым способом создания и тестирования различных идей.

Архитектура Model-View

Область, в которой, как правило, возникают проблемы с поддержкой в Smart UI приложениях – это бизнес-логика, и внесение изменений может стать очень неприятным процессом. Улучшения в этой области предлагает архитектура model-view (модель-представление), которая вытаскивает бизнес-логику в отдельную доменную модель. При этом данные, процессы и правила все сосредоточены в одной части приложения, как показано на рисунке 3-3.

Рисунок 3-3: model-view паттерн

Архитектура model-view является значительным улучшением по сравнению со Smart UI – например, ее гораздо легче поддерживать. Тем не менее, возникают две проблемы. Первое, поскольку пользовательский интерфейс и доменная модель настолько тесно интегрированы, затрудняется выполнение юнит тестирования. Вторая проблема вытекает из практики, а не из определения паттерна. Эта модель обычно содержит массу кода доступа к данным, а это значит, что модель данных содержит не только бизнес данные, операции и правила.

Классическая трехуровневая (three-tier) архитектура

Для решения проблемы с архитектурой model-view трехуровневая или трехслойная (three-tier или three-layer) модель отделяет код от доменной модели и помещает его в новый компонент под названием DAL. Это показано на рисунке 3-4.

Рисунок 3-4: Трехуровневый паттерн

Это большой шаг вперед. Трехуровневая архитектура является наиболее широко используемым паттерном для бизнес-приложений. Она не имеет ограничений относительно того, как реализован пользовательский интерфейс, и обеспечивает хорошее разделение понятий, не будучи слишком сложной. Также DAL может быть создан таким образом, что юнит тестирование будет относительно легким. Вы можете увидеть очевидное сходство между классическим трехуровневым приложением и MVC паттерном. Разница состоит в том, что поскольку UI слой напрямую соединен с «click-and-event» GUI фреймворком (таким как Windows Forms и ASP.NET Web Forms), становится почти невозможным выполнение автоматизированных юнит тестов. И поскольку UI часть трехуровневого приложения может быть очень сложной, мы имеем много кода, который не может быть тщательно протестирован.

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

Вариации MVC

Мы уже изучили основные принципы создания MVC приложений, и особенно то, как они относятся к реализации ASP.NET MVC. Другие интерпретируют аспекты паттерна по-другому и корректируют или иным образом адаптируют MVC для своих проектов. В следующих разделах мы представим краткий обзор двух наиболее распространенных вариантов на тему MVC. Понимание этих вариантов не является необходимым для работы с ASP.NET MVC. Мы включили эту информацию для полноты.

Model-View-Presenter паттерн

MVP является вариацией MVC, который разработан, чтобы соответствовать GUI платформам, сохраняющим состояние (stateful), таким как Windows Forms или ASP.NET Web Forms, и это стоящая попытка представить лучшие аспекты Smart UI без тех проблем, которые он обычно приносит.

В этом паттерне презентер (presenter) имеет те же обязанности, что и MVC контроллер, но он также имеет более непосредственное отношение к представлениям, напрямую управляя значениями, отображаемыми в UI компонентах, в зависимости от действий и данных, введенных пользователем. Существуют две реализации этого паттерна:

  • Реализация пассивного представления, в котором представление не содержит логики – это контейнер для элементов управления UI, которые напрямую управляются презентером.
  • Реализация надзирающего контроллера, в котором представление может быть ответственным за некоторые элементы логики представления, такие как связанные данные, и к источнику данных можно ссылаться из доменной модели.

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

Model-View-View Model паттерн

MVVM паттерн является самой последней вариации MVC. Он возник в 2005 году в команде Microsoft, которая разрабатывала технологию, ставшую Windows Presentation Foundation (WPF) и Silverlight.

В MVVM паттерне модели и представления играют те же роли, что и в MVC. Разница состоит в MVVM концепции модели представления, которая является абстрактным представлением пользовательского интерфейса. Как правило, это C# класс, который раскрывает оба свойства для данных, которые будут отображаться в интерфейсе, и операции по данным, которые могут быть вызваны из пользовательского интерфейса. В отличие от MVC контроллера, модель представления MVVM не имеет понятия, что существует представление (или любая конкретная UI технология). MVVM представление использует связывающую функцию WPF/Silverlight для двунаправленного связывания свойств, предоставляемых элементами управления в представлении (пункты в выпадающем меню или результат нажатия кнопки), со свойствами, предлагаемыми моделью представления.

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

Совет

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