Выступление на ADD2010: Silverlight/WPF: возврат от паттерна MVVM к MVP

Пару дней назад я упомянул, что подал тезис на конференцию разработчиков Application Developers Days 2010, которая пройдет в Ярославле 23-24 сентября. Сегодня меня обрадовали, объявили, что мой доклад прошел, его тема «Silverlight/WPF: возврат от паттерна MVVM к MVP»:

В данном докладе автор на примерах обрисует особенности реализации знаменитых паттернов MVP и MVVM, применяемых при разработке приложений на WPF и Silverlight. Даст их подробное сравнение на примере данных технологий, укажет основные плюсы и минусы реализаций данных паттернов, а так же обрисует доработанный паттерн MVP с облегченной моделью представления, который является синтезом паттернов MVP и MVVM для разработки приложений на данных технологиях.

Я уже довольно давно недоволен паттерном MVVM, а вот почему, и что я предлагаю взамен (это предложение строится на моем опыте, а так же опыте коллег-разработчиков WPF/Silverlight) я расскажу на конференции Application Developers Days 2010 в Ярославле. Доклад на 100% еще не готов, потому если есть какие-либо предложения, идеи или советы – буду рад комментариям. У меня осталась одна подписка Visual Studio 2010 Ultimate + MSDN Premium Subscription, которую, скорее всего я разыграю за интересный вопрос или предложение на конференции (если они действительно будут). Если нет, то отдам докладчику, который мне понравится своим докладом и которому она действительно нужна.

Полностью тезис можно прочитать в этом документе add.doc, основная идея доклада из тезиса ниже.

Возврат к паттерну MVP

Паттерн MVVM достаточно хорошо разрекламирован среди разработчиков Silverlight и WPF приложений, но как оказалось совершенен он не во всем. Как было описано в статье Джоша Смита, что нет смысла использовать паттерны проектирования для приложений, вроде «Hello, World!», но, к сожалению, во всех примерах реализации данного паттерна мы только такие приложения и видим, на практике же возникает больше вопросов и проблем, чем описано в подобных статьях.

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

В большинстве случаев реализации MVVM паттерна модель представления имеет очень много причин для изменений. Если нам нужно на представлении поменять немного логику, использовать другое связывание данных, то, скорее всего, нужно будет менять и логику в модели представления. Если поменялась модель, то нужно менять за ней и модель представления. Одни из самых важных принципов разработки – это «разделение ответственности» (Seperation of Concerns) и «принцип единственной ответственности» (Single Responsibility Principle). В случае модели представления эти принципы нарушены.

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

Комментарии (23)

rooks ( ) #
gravatar
>> Как было описано в статье Джона Смита...
Его зовут Джош(Josh)
Denis Gladkikh ( ) #
gravatar
rooks, fixed. Видимо, для глаз было более узнаваемо John.
Sergey Zwezdin ( ) #
gravatar
Интересные мысли. Но описаные, Денис, тобой проблемы паттерна MVVM решаются путем разделения представления/модели представления на несколько объектов. Тогда сохраняется SRP и поддерживать приложение становится проще простого, даже при его разрастании.
А паттерн MVP по моему опыту только наоборот добавляет много излишеств, хотя твои модификации может быть именят мое представление об этом.
Будет интересно поговорить на эту тему на мероприятии.

И да, MMVM тоже позволяет сделать несколько представлений на модель.
Андрей Майоров ( ) #
gravatar
Молодец, Дэн! И оформил все отлично. Есть, все таки, дисциплинированные программисты в родном отечестве. :)
force ( ) #
gravatar
Голова закружилось от слишком частого упоминания модели представления :) Может как-то попроще термин можно подобрать? а то реально путаюсь во всех этих моделях пока читаю. :)
Denis Gladkikh ( ) #
gravatar
force, а как я путался когда это писал, ты не представляешь ;) Можно называть вью-модэль, вроде покороче, так и привык называть, скорее всего на докладе так и будет.

Андрюха, это во мне еще кусочки аспиранта работают ;) Надо было бы набрать на TeX :)

Сергей, да конечно, такой подход встречается тоже, правда он уже немного отличается от стандартного MVVM, но все же. Есть и другие неприятности, которые мне не нравятся. Я не говорю что MVP намного приятнее MVVM, но все же постараюсь объяснить почему мне интереснее он.
Calabonga ( ) #
gravatar
Сколько бы моделей (паттернов) программирования реализующих принцип MVC не появилось (разные модификации и реализации), проблемные места и рулезные фишки будут у каждой из них. Другой момент, на сколько будет проще (качественнее, быстрее, дешевле) разработка приложения с использования того или иного шаблона, или даже без использования шаблона! И только программисту решать какой из шаблонов или никакого вообще использовать.
Кеша ( ) #
gravatar
А у меня со временем сложился такой опыт, любой шрот (от немецкого - корм для скота, в народе - сброд) "пропихивается" везде уже тем, что под функцией, формой или ещё чем, короче под софтом - вешается ярлык, что мол от того или иного паттерна - и мол никакой критике не поддаётся.
Очень часто под этим также "понимается" другое слово - стандарт - и всё ни чем такие софты, неважно как плохо они состряпаны, ничем их не сможешь как-бы улучшить, ведь уже по стандарту. Только с помощью "революции", когда такой софт умирает и на его место вроде другой "может"/"должен" придти - только тогда есть возможность что-либо в концепте изменить. И тогда такой софт переписывается. Хотя вроде всё было до сего момента хорошо. И паттерны правильные были взяты и вроде стандартами от Microsoft(a) "пользовались", а вот почему-то софт полностью переписывается.

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

Концептам, совершенствованию и самой реализации можно и не много сил тратить, ведь по стандарту-же.

Немного печальна такая постановка дел. С приветом
Кеша ( ) #
gravatar
тема интересная.
Документ конечно стоит того, что быть прочитаным. спасибо. Вообще не часто, но наблюдаю иногда твои высказывания, тексты. Желаю успехов и сил на данном поприще.

А дотошность в подходе к поставленой задаче - преветствую. На сегодняшний момент люди "теряют" это свойство. В большинстве всё на скорую руку, чтобы было быстро.
Denis Gladkikh ( ) #
gravatar
Кеша, спасибо за напутствие! Давно уже сам замечаю, что просто стало официальным использование MVVM и Prism среди фирм разработчиков Silverlight/WPF, и спрашивают и требуют знания, хотя сами особо не понимают зачем, но все же это рекомендация от Microsoft, значит must have. Посмотрим во что выльется этот доклад.
Max Paulousky ( ) #
gravatar
интересно
будем ждать небольшой сэмпл, построенный на основе нового подхода
Igor ( ) #
gravatar
Есть много плюсов от использования таких фреймворков как Prism
1. Во первых он достаточно хорош для многих типовых задач, и постоянно развивается, например в последнем выпуске добавили поддержку MEF
2. Намного проще найти и ввести нового девелопера в проект, поскольку зная PRISM можно получить общую картину о структуре проекта.

Но в принципе согласен,что ViewModel в нынешнем виде гибрид между данными и презентором.
Anvaka ( ) #
gravatar
Денис, извините, но я с вами не соглашусь. А вот Сергей заметил абсолютно верно. Проблема SRP появляется только из-за кода, который пишет разработчик, а не из-за MVVM'a. Стоит разделять большие viewmodel на более мелкие. И, пожалуй, это и есть настоящий MVVM.

Имхо основная проблема с MVVM'ом - это увеличение сложности воспроиятия кода. Часто неочевидно кто является контектом данных и куда идет привязка, посредством каких конверторов. Но на помощь приходит культура документирования кода (указывать у XAML'a кто в DataContext'e, в коде говорить ViewModel'ом кого мы являемся, и т.д.)
Denis Gladkikh ( ) #
gravatar
Anvaka, спасибо за размышления. Попробую рассмотреть все варианты в докладе.
Severn ( ) #
gravatar
Сформулирую вопрос.
В приложении хочется определить команды в меню - в главном меню программы, в контекстных меню на формах объектов. Может быть, какие-то команды реализовать на формах в виде кнопок.
Ну, какие-то стандартные команды я могу предусмотреть заранее - типа Напечатать, Удалить объект и т.п. А какие-то команды появляются в ходе реализации и дальнейшего расширения системы.
Например, у класса Заказ может появиться команда ВвестиОплату. (Ну, на самом деле при этом вводится объект класса ПриемДенег, со ссылкой на этот Заказ.)
Фишка в том, что модуль (проект) Заказы.dll разрабатывался раньше, и о модуле (проекте) Касса.dll - содержащем класс ПриемДенег - он ничего не знает.
Более того, если в программу подключен только модуль Заказы.dll, то и команды оплаты на форме Заказа появляться не должно. Она, вероятно, будет описана и как-то зарегистрирована либо в модуле Касса.dll, либо в каком-то третьем модуле - скажем, ОплатаЗаказов.dll, или ФормыЗаказов.WPF.dll.
И вот при старте программа подключает модули, собирает информацию о содержащихся в них классах.
И!
При выводе формы Заказа она должна как-то выяснить - не было ли для этого класса Заказ подключено каких-то особых команд в других модулях.
(Например, ОплатаЗаказа в модуле ФормыЗаказов.WPF.dll, и ДоставкаЗаказа в модуле Перевозки.dll)
И подключить эти команды к этой форме. Выведя соотв. пункты в контекстном меню или каки-нибудь кнопочки на панели.
Предложите вариант реализации такого механизма регистрации команд и их привязки ?
Denis Gladkikh ( ) #
gravatar
Severn, ваша проблема, приблизительно ясна. Могу попробовать вам подсказать решение по live - skype или что-то другое.

А так, может быть в будущем попробую описать решение проблемы у себя в блоге.
Severn ( ) #
gravatar
Давайте по Skype - severn_lipes
Когда Вы там бываете ?
Александр ( ) #
gravatar
Ядреная смесь представлений :)

"Модель на самом деле вообще не имеет представления о том, что существуют модель представления и представление."
Denis Gladkikh ( ) #
gravatar
Александр, а представьте как это писать и рассказывать :)
gromas ( ) #
gravatar
Severn, в Вашем случае, думаю, команды надо подключать так же как и данные - внешний источник с поддержкой IEnumerable/IQueryable. Заполняете его командами и передаете в конструктор модели представления, а в представлении - шаблон, строящий по этим данным (списку/дереву команд) меню.
gromas ( ) #
gravatar
Александр, ждем доклад. Надеюсь, в интернет выложите?
Denis Gladkikh ( ) #
gravatar
Это, наверное, ко мне было обращение? Либо (а) будет запись выступление, либо (б) запишу доклад/скринкаст
gromas ( ) #
gravatar
Да, Денис, совершенно верно. Приношу извинения :)
Добавить комментарий
Если вы хотите получать уведомления о новых комментариях к данному топику, укажите, пожалуйста, email и отметьте соответствующий пункт в форме. Если вы хотите добавить код в тексте комментария, то заключите его внутри тега [code]...[/code], более того можно уточнить язык, на котором написан данный код при помощи [code cs]...[/code], где вместо cs могут быть cs, html, xml, java, js, php, sql, cpp, css.

 

busy