MVC, MVP, MVVC - как разобраться?

IT IT
Здравствуйте, andyag, Вы писали:

A>Подскажите пожалуйста что почитать на тему MVC, MVP, MVVC, чтобы разобраться.


На самом деле всё не так сложно, как кажется. Проблема большинства интерпретаций паттерна в том, что они не объясняют, зачем вообще всё это надо. Если разобраться с первопричинами, то всё остальное становится просто и понятно. Т.е. нужно просто посмотреть на то, какие реальные проблемы решают эти паттерны и каким образом, и всё станет на свои места.

При разработке UI решаются три задачи:

  • (M) получение/сохранение/работа с данными,
  • (V) рендеринг интерфейса,
  • (x) увязывание данных с интерфейсом.

В соответствии с открытым в начале XXI века Законом cохранения cложности , густой замес всех этих задач в одном месте даёт многократное увеличение сложности результата, что в свою очередь для навороченного интерфейса приводит к быстрой и неизбежной потере контроля над кодом. MVx как раз и предназначены для того, чтобы решить эту проблему путём разделения сфер влияния и уменьшения связей между обозначенными частями кода и вместо умножения сложностей всех трёх частей получить в идеале их сумму. Идеал достигается при условии, что все три части вообще ничего не знают друг о друге.

У всех трёх MVx есть общие M и V. С них и начнём.

Model

Это те самые данные, которые мы отображаем с помощью нашего интерфейса. Можно было бы сказать, что с этим всё понятно, но есть один маленький вопрос, который вносит некоторую путаницу в паттерн. Вопрос – кто отвечает за получение и сохранение данных, сама модель или кто-то другой, кто-то внешний по отношению к нашему компоненту или же это обсуждаемый ниже ‘x’? По идее в MVx должна появиться ещё одна буква – S(ervice) и тогда всё стало бы на свои места, но оставим это на совести придумывальщиков паттернов.

View

Это собственно визуальный интерфейс. В MFC и WinForms это код создания формы под катом, в ASP.NET — html, в WPF и Silverlight – XAML. Надеюсь это не должно вызывать никаких сложностей.

MVC

MVC – это базовый паттерн, классика жанра. Я бы даже сказал, что сегодня это скорее общий термин для группы паттернов, которым ввиду разнообразия не имеет смысла давать отдельные названия. Как мы выяснили, в идеале все три части должны знать друг о друге как можно меньше. Все эти паттерны как раз и отличаются тем, кто о ком что знает и насколько подробно. Например, в MFC и WinForms контроллер увязывает модель с интерфейсом, заполняет форму взятыми откуда-то из S(ervice) данными и реагирует на события от интерфейса. Контроллер знает всё о модели и интерфейсе, интерфейс знает о контроллере, модель не знает ничего. К тому же в WinForms используя binding можно значительно ослабить связь между всеми тремя частями. В некоторых реализациях, например, ASP.NET MVC разработчикам удалось добиться того, что интерфейс (View) напрямую не взаимодействует с контроллером, а контроллер знает совсем чуть-чуть о View. Зато View всё знает о модели. Более того, модель специально строится под нужды интерфейса и, если в приложении есть другие модели, например, модель данных приложения или объектная модель приложения, то это проблемы самого приложения, а ASP.NET MVC хочет свою собственную модель для своих собственных нужд.

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

Ещё одной фундаментальной проблемой разработки UI является тестирование визуальных компонентов. В общем случае эта проблема решается только с использования специальных средств тестирования имитирующих действия пользователя, которые до сих пор не получили широкого распространения. Но если нельзя протестировать всё, то хорошо бы уметь тестировать хотя бы что-то, желательно самое запутанное. View на сегодняшний день – это чистая или почти чистая декларация или вообще визуальный редактор. Как таковой императивной логики там либо нет совсем, либо её мало и она не вызывает затруднений. Поэтому тестировать нужно прежде всего модель и контроллер. Классический MVC не решает этой проблемы. Хотя в ASP.NET MVC эта проблема решена на уровне фреймворка за счёт слабых связей контроллера и View.

MVP

По сути, у MVP одна единственная задача – полностью отделить View от контроллера и дать возможность использовать сменные View. Сама по себе идея сменных View утопична. В теории это выглядит красиво. Но мы все прекрасно знаем, чем теория отличается от практики. На практике же получается, что для более менее сложных UI контроллеры, например, для Web и Win, отличаются принципиально, начиная с обработки событий и заканчивая специфичной потребностью в данных. А для простых UI, где это могло бы сработать, встаёт вопрос о целесообразности применения данного паттерна вообще, т.к. за счёт его применения усложнение мы получим по любому, а вот будет ли от этого хоть какой-нибудь эффект ещё вопрос.

Но! MVP как раз помогает нам решать проблему тестирования наших визуальных компонент и уже поэтому имеет право на существование. По сути MVP отличается от MVC лишь введением интерфейса между View и контроллером, который теперь назван презентером. Т.е. на диаграмме к трём квадратикам добавляется четвёртый – интерфейс и все связи от модели и контроллера к View протягиваются через него.

MVVM

Говоря о WinForms я уже упоминал binding. Binding позволяет контроллеру знать поменьше как о модели, так и о View. Связь модели и View задаётся декларативно во View, в результате хоть и получается связь View -> Model, но не очень сильная. Хотя, с другой стороны и не очень надёжная. В отличие от WinForms в XAML binding ещё более продвинут, и позволяет связывать с формой не только данные, но и действия. Из функционального программирования мы знает, что функция – это объект, а раз так, то никто не мешает этот объект задать в виде свойства нашей модели и декларативно связать его с соответствующим свойством во View. В результате мы получаем идеал ООП – самодостаточный объект с инкапсулированными данными и поведением, который абсолютно ничего не знает о View.

ViewModel и есть этот самый объект. Фактически мы совместили в одном объекте функции модели и контроллера и назвали вот так замысловато. Это и понятно. От контроллера не осталось практически ничего. Функции обмена данными View и модели полностью берёт на себя binding. Реакцию модели на действия пользователя обеспечивается этим объектом, опять же посредством binding. И главное, такие объекты легко тестировать по причине их самодостаточности.

Остаётся лишь один неясный вопрос, а что же такое первое M в MVVM. Видимо это модель данных или какая-то другая модель приложения. Последнее время тенденция создания отдельной модели для конкретного View становится всё более популярной и с практической точки зрения это вполне оправдано. ASP.NET MVC вообще объявил модель своей собственностью, а на остальные ему начхать.

Итого

Всё в этом мире существует по какой-либо причине. Поняв эту причину можно понять это самое “всё”. В программировании большинство вещей, особенно сходу не совсем понятных, крутится вокруг управления сложностью. Сложность в разработке UI в наличии сильных связей между M, V и C. Абсолютно все MVC паттерны решают одну и ту же задачу – устранение или ослабление этих связей. Это — ключевой момент в понимании этого паттерна. Разбираясь, как работает тот или иной MVC паттерн, ищите эти связи и разбирайте способы их устранения. Поняв это, вам не составит труда понять сам паттерн и его предназначение. И главное понять а надо ли оно вам.
andyag
andyag
01.11.2011 06:06
Здравствуйте, IT, Вы писали:

IT>На самом деле всё не так сложно, как кажется.


Большое спасибо за ответ — очень внятно и грамотно всё написано.
gravatar
Аноним
06.11.2011 04:06
Здравствуйте, IT, Вы писали:

IT>MVVM


MVVM придумали для того что бы посадить тему лебедева на Expresion Blend и никогда не открывать обычному програмисту ни XAML ни визуальный дизайнер.

IT>Остаётся лишь один неясный вопрос, а что же такое первое M в MVVM. Видимо это модель данных или какая-то другая модель приложения. Последнее время тенденция создания отдельной модели для конкретного View становится всё более популярной и с практической точки зрения это вполне оправдано. ASP.NET MVC вообще объявил модель своей собственностью, а на остальные ему начхать.


Щас будет холивар философия. Без MVx никто не запрещает на каждый UI-кусочек создавать отдельную модель. Проблема остается с, назову это, Shared Model. Например ID пользователя, текущая тема, профль пользователя, и чтоб не скучно было страна apple store магазина.
gravatar
Аноним
30.05.2013 01:54
Здравствуйте, IT, Вы писали:

IT>На самом деле всё не так сложно, как кажется.


Это верно, а если воспользоваться правильным инструментарием (Xomega.net) то станет совсем легко.
Очень полезные статьи на codeproject.com:
Take MVC to the Next Level in .NET
How to Build Powerful Search Forms
Cascading Selection the MVC Way
How to Build Flexible and Reusable WCF Services
SE
SE
31.05.2013 06:01
Здравствуйте, Аноним, Вы писали:

Если еще не упоминалось, добавлю
http://joel.inpointform.net/software-development/mvvm-vs-mvp-vs-mvc-the-differences-explained/
gravatar
Аноним
11.06.2013 10:12
Здравствуйте, IT, Вы писали:

IT>Model


IT>Это те самые данные, которые мы отображаем с помощью нашего интерфейса. Можно было бы сказать, что с этим всё понятно, но есть один маленький вопрос, который вносит некоторую путаницу в паттерн. Вопрос – кто отвечает за получение и сохранение данных, сама модель или кто-то другой, кто-то внешний по отношению к нашему компоненту или же это обсуждаемый ниже ‘x’? По идее в MVx должна появиться ещё одна буква – S(ervice) и тогда всё стало бы на свои места, но оставим это на совести придумывальщиков паттернов.


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

Например:
база данных (MS SQL Server), пользовательский интерфейс (client application), слой доступа к данным (WCF) — это MVC.
Но в пользовательском интерефейсе свой MVC: WCF-объекты, XAML, ViewModel с коммандами.
В данном случае и базу данных можно рассматривать как MVC: таблица, представление, хранимые процедуры.

Я видел весьма изощренные иерарахии с явно выделенными элементами вариантов MVC вплоть до 3-6 уровней с прицелом на бесконечность.