Как стать автором
Обновить

Комментарии 36

Открыл для себя давно уже паттерн MVPVM для XAML платформ. Это просто смесь MVP + MVVM.
Там где удобно использовать bindings — просто используешь всю мощь MVVM. А там где нужно вызвать что-то вроде ListBox.ScrollIntoView — просто используешь мощь MVP — делаешь метод для интерфейса представления и его просто вызываешь.
Спасибо, добрый человек.
Во-первых, спасибо Вам за статью, написанную ранее по этой же теме (я про Ваш блог).
Во-вторых, MSDN-журнал уже писал об этом.
IMHO, MVPVM отлично подходит для Windows Forms. Для каждого интерфейса представления должна быть реализована функция, типа «InitializeBindings», где для каждого контрола связывание должно происходить.
IMHO, MVPVM отлично подходит для Windows Forms. Для каждого интерфейса представления должна быть реализована функция, типа «InitializeBindings», где для каждого контрола связывание должно происходить.

Это уже тонкости реализации. Я просто говорю брать лучшее от двух. В случае с MVP приходится писать много кода, который связывает View и Presenter, в случае с MVVP этого делать не нужно в 80% случаях, но в оставшихся 20% (ототбражение Popup, вызова ListBox.ScrollIntoView ) придется писать безумных Iteraction, хотя иногда это намного проще решается при помощи MVP связки.
Когда у меня была идея написать больше одного приложения для Windows Store я сделал что-то вроде Framework для себя github.com/outcoldman/Framework под эту платформу. И удачно реализовал gMusicW на нем (http://apps.microsoft.com/windows/en-us/app/gmusicw/939f0859-1413-4a52-9ab6-6e50405c8c2e). Но в итоге из-за нехватки времени просто стал контрибютить дальше только для gMusicW. Но в целом, Framework может показать пару интересных идей.
Не могли бы вы взглянуть на bitbucket.org/igor_kostromin/wpf-mvp/ (ссылка на пример)? Интересно ваше мнение о такой реализации — похоже, что у нас и получился именно MVPVM, о котором вы говорите.
Да очень похоже MVPVM. Ничего хорошего или плохого сказать не могу о реализации, пример слабоват. Но главное, чтобы для вас работало как нужно ;)
Мне кажется в описании View-Model вкралась ошибочка в последнем пункте. Вполне возможно и даже принято связывать одну View-модель с несколькими View. Очень распространено в master-details представлениях.
Не совсем понятно, а не приведет ли это к чрезмерному разрастанию View-модели, которая станет поистине универсальной и огромной, «на все случае (виды) жизни»?

В классическом описании модель может представлять себе один экземпляр.
Все зависит от программиста, но такого ограничения ни физически, ни логически нет. Для примера возьмем упомянутый паттерн master-details & WPF. Создаем в мастере список view-моделей, привязываем его к лист-боксу и задаем отображение для элемента. Это первое view для нашей view-модели. Далее создаем ContentControl и привязываем наш список с заключительным слешем (кто не знает, это привязывает выбранный элемент списка). Создаем отображение details для той же view-модели. Это будет второе view. Есть примеры отображения модели как графика и как списка или разных графиков и много другого разного. Главное, что идея MVVM не ограничивает привязку одного отображения.
Трудно не согласится, что все, в конечном итоге, сводится к людям и их профессионализму.
В любом случае, если такой подход решает поставленные задачи, то она всегда будет хорошей :)
НЛО прилетело и опубликовало эту надпись здесь
Таких частных случаев как пионеров нерезанных. Я привел самый распространенный, без которого не обходится ни одна аппликация. Кстати Майкрософт по этому поводу говорит следующее: «There is typically a one-to-one relationship between a view and its view model». Другими словами это типично, но не обязательно. Пруфлинк msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx.
MVC, это не паттерн — это парадигма.
При MVC пользователь взаимодействует с Controller а не со View
Не ясно, что такое View в этом случае… Позвольте утверждать, что аббревиатурой MVC обычно понимают целое семейство паттернов, среди которых можно выделить первоначальный вариант.
www.itu.dk/courses/VOP/E2005/VOP2005E/8_mvc_krasner_and_pope.pdf
К тому же нужно разобраться в терминах, что есть шаблон. а что есть парадигма.
Но так как вы выделили, что:
что аббревиатурой MVC обычно понимают целое семейство паттернов

уже говорит о том что вы подразумеваете парадигму.
Я могу ошибаться, но вроде как парадигма это совокупность действий, определяющих стиль. Т.е. парадигма в программровании — это семейство нотаций, различающихся по методикам. Примеры:
1. Функциональное программирование
2.Логическое программирование
3. ООП.

С другой стороны, Вы правы, в классическом MVC действия пользователя передаются в контроллер. Наверное, это имелось ввиду.
Я могу ошибаться, но вроде как парадигма это совокупность действий, определяющих стиль. Т.е. парадигма в программровании — это семейство нотаций, различающихся по методикам.

Вы правы, так оно и есть.
MVC — это парадигма, в которую вписываются семейство паттернов. Паттерн — это реализация и они различны, как вы сказали ранее (М.Фаулер о MVC)
Спасибо за статью.
Вопрос: как практически реализовать MVPVM в Windows Forms?
Сейчас у меня есть классы, в которых реализована логика и хранятся данные, есть формы в которых реализован интерфейс, в классе формы есть ссылка на экземпляр класса логики/данных и дальше происходит следующее:
когда мне нужно выполнить действие, то я ловлю событие нажатия на кнопку, метод обработки события сначала собирает данные из контролов формы, обновляет состояние класса логики и вызывает метод класса логики, затем обновляет интерфейсные контролы.
А как можно улучшить структуру?
Добрый день,
> когда мне нужно выполнить действие, то я ловлю событие нажатия на кнопку, метод обработки события сначала собирает данные из контролов формы, обновляет состояние класса логики и вызывает метод класса логики, затем обновляет интерфейсные контролы.
Вы описали логику Presentera. В Вашем случае, для практики, я бы рекомендовал обратиться к использованию паттерна MVP,
Несколько некорректно выглядит вот это утверждение об MVC: "Модель использует событие о том что она изменилась, и все подписанные на это события Представления, получив его, обращаются к Модели за обновленными данными, после чего их и отображают" в связке с указанием о том, что этот подход применяется в ASP.NET MVC. Конкретно там View не подписывается на изменения модели и никак не следит за ними. Эта роль отводится контроллеру, он реагирует на действие пользователя, меняет модель и отдает View измененные данные для отображения.
Мне одному кажется, что статьи про архитектуру ПО сильно проигрывают, если не дополнены примерами кода?
НЛО прилетело и опубликовало эту надпись здесь
Не вижу в этом вообще никакой проблемы. Среднестистический девелопер в команде постоянно работает с такими колоссальными объемами кода, на фоне которых примеры реализации архитектурных паттернов — капля в море. Тем более их всегда можно залить на гитхаб или спрятать под спойлер.

Вот пример статьи уважаемого мной товарища про модули в Java Script habrahabr.ru/post/181536/. Статья большая? Большая. Стало от этого хуже? Нет, не стало, статья замечательная и отвечает на 90% вопросов, связанных с паттернами модулей в Java Script.
Пожалуйста, больше никогда не пишите JavaScript раздельно.
А как предотвратить лишние обновления Представления, если приходят повторяющиеся события об изменении данных в процессе пересчета Модели?
Видимо тут все сильно зависит от платформы. Если это XAML технология построенная на Bindings (XAML, Angular) то там представление обновится только тогда, когда данные реально поменяются.
В противном случае можно представление разбивать на более мелкие и обновлять только их.
Спасибо за ответ. Только не очень понятно про разбитие представления. Можно, я попробую описать пару проблемных примеров.

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

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

Как избежать этих перерисовываний в обоих примерах? По идее модель должна уведомить представление только один раз — после всех расчетов, а представление отобразит окончательное значение один раз. Но как в модели определить, что именно это изменение будет последним? Ведь любая модификация данных может либо стать последней в алгоритме, либо за ней последуют другие модификации. В какой момент модель должна отправить сообщение представлению?
Как при связывании данных решается эта проблема?
В MVVM обычно можно создать привязку, которая будет отправлять данные в вид или модель вида с задержкой, игнорируя быстро происходящие изменения. В популярных фреймворках это делается одной строчкой: WPF, Knockout.
А без задержки никак нельзя?
Если хочется сэкономить пару перерисовок, можно не заниматься преждевременной оптимизацией, и оставить всё, как есть.
В некоторых фреймворках, например Angular, изменение модели на вид никак не влияет, фреймворк сам решает, когда перечитать модель, и такие оптимизации не понадобятся.

В примере 1, если одно действие пользователя вызовет добавление десятков строк в лог, а сама модель за лог не отвечает, задержка будет неплохим вариантом. Если лог генерируется в UI-потоке, можно поставить задержку в 1 мс, что по факту приведёт к 1 перерисовке сразу после завершения вычислений и освобождения UI-потока. Задержки по полсекунды нужны для других случаев, например, когда ввод текста пользователем вызывает отправку запросов на сервер (поисковые подсказки и т.д.).

В примере 2, результатом расчётов, видимо, является одно значение, вот пусть модель его и считает, а результат передаёт в модель вида, только когда он готов. Разделение на M и VM нужно, в том числе, и для этого.
Спасибо за разъяснения. Посмотрел про Angular — там красивые уроки и примеры. Получается, что в этом фреймворке модель пассивная и сама не отправляет сообщения. Как же все-таки Angular определяет, что именно в $scope изменилось в модели по сравнению с предыдущей версией?
На то или иное изменение во view вызывается метод $scope.$apply, например (цитата из angular.js, код стандартного обработчика для checkbox'а):

...
element.on('click', function() {
    scope.$apply(function() {
      ctrl.$setViewValue(element[0].checked);
    });
  });
...


$scope.$apply() в своем коде вызывает $scope.$digest (см. исходный код).

При этом у $scope'а есть свойство $$watchers — это функции, которые по вызову вычисляют какое-то определенное для каждой из них выражение (первый аргумент), и если оно поменялось с момента предыдущего вызова, вызывают callback (второй аргумент) [ссылка на синтаксис создания $watcher'а. В большинстве случаев эти штуки добавляются встроенными директивами].

$scope.$digest() вызывает все $scope.$$watchers по очереди, сравнивая старое и новое значение выражений для каждого из них (см. тело функции $digest) и, если старое и новое значения для данного $watcher'а различаются, запускается callback соответствующего $watcher'а, принимающего oldValue и newValue в качестве аргументов.

Соответственно уже конкретный callback может делать что угодно — менять какое-то другое выражение, добавлять/менять/убирать разметку определенного элемента и т.п.

Как-то так)
В последнее время на Хабре, да и в принципе в головах разработчиков так часто мусолится тема MVC/MVP/MVVM/MV*, начало всплывать такое множество различных вариаций этих паттернов, что в какой-то момент задумываешься: а где же, блин, отличия между ними :-) Приходится (зачем?) глубоко вчитываться во все описания и приходить к выводу, что всё это многообразие обусловлено лишь ограничениями\спецификой случаев, в которых их применяют. И «толщиной» каждого из слоёв — где-то больше кода во вью, где-то в контроллере. Как результат — когда кто-то рассказывает тебе о MV* или задаёт тебе вопрос на эту тему, уже невольно теряешься: а что конкретно этот человек понимает под этими буквами. Все эти различия и нюансы настолько незначительны и не принципиальны…
Добрый день,
Позвольте не согласиться с Вашим последним утверждением. Различия и нюансы сильно влияют на дальнейшее развитие продукта в целом.
На мой взгляд, применение определенной архитектуры — это стратегия развития продукта, его возможностей в будущем. Например, через 2-3 релиза, учитывая, что у нас RUP.
Я пытался сказать, что в теории, статьях, картинках, разговорах — различия между паттернами высосаны из пальца и не принципиальны. Мало смысла пытаться забивать себе голову тем, как MVC отличается от, допустим, MVPVM. На практике разница будет, но не в принципиальном подходе, а небольших деталях реализации. И вытекать она будет из требований и условий проекта, а не решений сверху «давайте здесь будет использовать MVP, а вот здесь — MVVM». И всё-равно в каждом проекте будет своя «версия» MV*, отличающаяся от теории. Даже в пресловутом ASP.NET MVC не то, что описано в данной статье.
И вытекать она будет из требований и условий проекта, а не решений сверху «давайте здесь будет использовать MVP, а вот здесь — MVVM». И всё-равно в каждом проекте будет своя «версия» MV*, отличающаяся от теории.

Верные слова! Выбирается только исходя из целей и трудозатра.
Спасибо за статью, Сергей!

В секции Model-View-Controller в качестве признака Контроллера указан пункт «Контроллер определяет, какие представление должно быть отображено в данный момент;», однако на прикрепленной вами диаграмме не указана определяющая связь от Контроллера к Представлению. Скорее, указана определяющая связь от Представления к Контроллеру. Я правильно понимаю, что это противоречие?

Возможно, вы имели в виду что-то вроде www.sitepoint.com/getting-started-with-mvc с диаграммой

image

В этой диаграмме действительно показана определяющая роль Контроллера при выборе Представления.




Также должен сказать, что в ряде обучающих статей на тему (например, в Википедии ru.wikipedia.org/wiki/Model-View-Controller) действия пользователя передаются не в Представление, а в Контроллер. Но тут стоит сказать, что общее несоответствие в этой детали по поводу MVC мы можем наблюдать во всех статьях по теме.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории