Модель View View-Model была разработана Microsoft для целевых платформ разработки пользовательского интерфейса, которые поддерживают программирование на основе событий, в частности Windows Presentation Foundation (WPF) и Silverlight на платформах .NET с использованием языков XAML и .NET. За прошедшие годы многие Javascript-фреймворки, такие как Angular, Knockout и ExtJS, приняли шаблон.
Как и большинство программных шаблонов, MVVM имеет свои подходящие применения и свои злоупотребления. При каких условиях целесообразно использование MVVM? Когда это опрометчиво?
Ответы:
MVVM предназначен для использования там, где необходимо сложное взаимодействие с пользователем с использованием высокоточных пользовательских интерфейсов (например, WPF ).
Для пользовательских интерфейсов, где такого рода расширенное взаимодействие не требуется, MVVM может быть излишним; MVP может быть более естественным выбором. Для веб-приложений лучше всего подходит MVC. Для очень маленьких приложений, которые никогда не станут больше (например, для небольших утилит Winforms), достаточен выделенный код.
источник
Иногда MVVM может быть ловушкой. Исходя из моего опыта, он предпочитает CRUD-подобные приложения (формы поверх данных) по сравнению с более ориентированными на задачи пользовательскими интерфейсами. Я не говорю, что это подразумевает плохую архитектуру для внутренних / других уровней в приложении, но я видел много MVVM-приложений с архитектурой "DDD light". Я не знаю, почему, может быть, именно потому, что привязка настолько проста, и очень просто настроить приложение с ORM и MVVM / Binding, используя объекты домена POCO / Anemic.
источник
MVVM - это бинты для плохо спроектированных слоев привязки данных. В частности, он широко использовался в мире WPF / silverlight / WP7 из-за ограничений в привязке данных в WPF / XAML.
С этого момента, я собираюсь предположить, что мы говорим о WPF / XAML, поскольку это прояснит ситуацию. Давайте рассмотрим некоторые недостатки, которые MVVM намеревается устранить в WPF / XAML.
Форма данных против формы пользовательского интерфейса
«VM» в MVVM создает набор объектов, определенных в C #, которые отображаются на набор объектов представления, определенных в XAML. Эти объекты C # обычно подключаются к XAML через свойства DataContext в объектах представления.
В результате граф объекта viewmodel должен отображаться на графе объекта презентации вашего приложения. Это не означает, что сопоставление должно быть взаимно-однозначным, но если элемент управления списком содержится в элементе управления окна, то должен быть способ добраться от объекта DataContext окна до объекта, который описывает данные этого списка.
Граф объекта модели представления успешно отделяет граф объекта модели от графа объекта пользовательского интерфейса, но за счет дополнительного слоя модели представления, который должен быть построен и поддерживаться.
Если я хочу переместить некоторые данные с экрана A на экран B, мне нужно возиться с моделями представления. По мнению делового человека, это изменение пользовательского интерфейса. Это должно происходить исключительно в мире XAML. К сожалению, это редко может. Хуже того, в зависимости от того, как структурированы модели представления и насколько активно изменяются данные, для выполнения этого изменения может потребоваться совсем небольшая повторная маршрутизация данных.
Обойти невыразительную привязку данных
Привязки WPF / XAML недостаточно выразительны. Вы в основном получаете способ добраться до объекта, путь свойства для обхода и связывающие преобразователи, чтобы адаптировать значение свойства данных к тому, что требует объект представления.
Если вам нужно привязать свойство в C # к чему-то более сложному, вам не повезло. Я никогда не видел приложение WPF без конвертера привязки, который превращал бы true / false в Visible / Collapsed. Многие приложения WPF также имеют свойство NegatingVisibilityConverter или аналогичное, которое меняет полярность. Это должно быть отключение сигнала тревоги.
MVVM дает вам рекомендации по структурированию кода C #, которые можно использовать для сглаживания этого ограничения. Вы можете выставить свойство на вашей модели представления с именем SomeButtonVisibility и просто связать его с видимостью этой кнопки. Теперь ваш XAML хорош и хорош ... но вы превратились в клерка - теперь вы должны выставлять + обновлять привязки в двух местах (пользовательский интерфейс и код на C #), когда ваш пользовательский интерфейс развивается. Если вам нужна эта же кнопка для отображения на другом экране, вы должны выставить похожее свойство в модели представления, к которой может получить доступ этот экран. Хуже того, я не могу просто посмотреть на XAML и увидеть, когда кнопка будет видна больше. Как только привязки становятся немного нетривиальными, я должен выполнять детективную работу в коде C #.
Доступ к данным агрессивно ограничен
Поскольку данные обычно поступают в пользовательский интерфейс через свойства DataContext, трудно представить глобальные данные или данные сеанса единообразно во всем приложении.
Идея «пользователя, вошедшего в данный момент», является отличным примером - часто это действительно глобальная вещь в экземпляре вашего приложения. В WPF / XAML очень сложно обеспечить глобальный доступ к текущему пользователю согласованным образом.
Что я хотел бы сделать, так это использовать слово «CurrentUser» в привязках данных, чтобы свободно ссылаться на пользователя, вошедшего в систему. Вместо этого я должен убедиться, что каждый DataContext дает мне способ добраться до текущего объекта пользователя. MVVM может приспособиться к этому, но модели представлений будут беспорядочными, поскольку все они должны предоставлять доступ к этим глобальным данным.
Пример, где MVVM падает
Скажем, у нас есть список пользователей. Рядом с каждым пользователем мы хотим отобразить кнопку «удалить пользователя», но только в том случае, если в данный момент зарегистрированный пользователь является администратором. Кроме того, пользователям не разрешается удалять себя.
Объекты вашей модели не должны знать о текущем вошедшем в систему пользователе - они будут просто представлять записи пользователя в вашей базе данных, но каким-то образом зарегистрированный в данный момент пользователь должен подвергаться привязкам данных в строках списка. MVVM требует, чтобы мы создавали объект viewmodel для каждой строки списка, которая составляет текущего зарегистрированного пользователя с пользователем, представленным этой строкой списка, а затем предоставляет свойство «DeleteButtonVisibility» или «CanDelete» для этого объекта viewmodel (в зависимости от ваших чувств о привязке конвертеров).
Этот объект будет выглядеть очень похожим на объект User во многих других отношениях - ему может потребоваться отразить все свойства объекта пользовательской модели и переслать обновления этих данных при их изменении. Это кажется очень странным - опять же, MVVM превращает вас в клерка, заставляя вас поддерживать этот объект, похожий на пользователя.
Подумайте - вам, вероятно, также необходимо представить свойства вашего пользователя в базе данных, модели и представлении. Если у вас есть API между вами и вашей базой данных, то это еще хуже - они представлены в базе данных, сервере API, клиенте API, модели и представлении. Я бы не решался принять шаблон проектирования, в который добавлялся еще один слой, к которому нужно прикасаться при каждом добавлении или изменении свойства.
Хуже того, этот уровень масштабируется в зависимости от сложности вашего пользовательского интерфейса, а не от сложности вашей модели данных. Часто одни и те же данные представлены во многих местах и в вашем пользовательском интерфейсе - это не только добавляет слой, но добавляет слой с большой дополнительной площадью поверхности!
Как все могло быть
В случае, описанном выше, я хотел бы сказать:
CurrentUser будет открыт для всех XAML в моем приложении. Идентификатор будет ссылаться на свойство в DataContext для строки моего списка. Видимость конвертируется из логического значения автоматически. Любые обновления Id, CurrentUser.IsAdmin, CurrentUser или CurrentUser.Id будут инициировать обновление видимости этой кнопки. Очень просто.
Вместо этого WPF / XAML заставляет своих пользователей создавать полный беспорядок. Насколько я могу судить, некоторые творческие блоггеры добавили имя в этот беспорядок, и это имя было MVVM. Не обманывайте себя - это не тот же класс, что и шаблоны проектирования GoF. Это уродливый хак, чтобы обойти уродливую систему привязки данных.
(Этот подход иногда упоминается как «Функциональное реактивное программирование» на случай, если вы ищете дальнейшее чтение).
В заключение
Если вы должны работать в WPF / XAML, я все еще не рекомендую MVVM.
Вы хотите, чтобы ваш код был структурирован, как в приведенном выше примере «как все могло бы быть» - модель экспонировалась непосредственно для просмотра со сложными выражениями привязки данных + гибкими приведениями значений. Это намного лучше - более читабельно, более доступно для записи и более легко обслуживаемо.
MVVM говорит вам, чтобы структурировать ваш код более подробным и менее понятным способом.
Вместо MVVM создайте материал, который поможет вам приблизиться к хорошему опыту: Разработайте соглашение для последовательного представления глобального состояния вашему пользовательскому интерфейсу. Создайте себе некоторые инструменты из конвертеров связывания, MultiBinding и т. Д., Которые позволяют вам выражать более сложные выражения связывания. Создайте для себя библиотеку конвертеров привязки, чтобы облегчить общие случаи принуждения.
Еще лучше - замените XAML чем-то более выразительным. XAML - это очень простой формат XML для создания экземпляров объектов C # - не составит труда найти более выразительный вариант.
Моя другая рекомендация: не используйте наборы инструментов, которые навязывают подобные компромиссы. Они повредят качеству вашего конечного продукта, подталкивая вас к дерьму, как MVVM, вместо того, чтобы сосредоточиться на проблемной области.
источник
Мне действительно нравится MVVM, и я нахожу его проблемы мотивирующими и вижу много преимуществ, но ...
Для приложений или игр, которые требуют большого количества пользовательского интерфейса / кода взаимодействия, чтобы добавить множество пользовательских поведений, сохраняя при этом работоспособность - часто лучше использовать немного грязный MVVM - используйте его, когда он полезен или в большей степени ориентирован на данные, чем центральные области взаимодействия кода. Скажем, вы хотите создать элемент управления и переместить его между различными родительскими элементами управления или иным образом кэшировать его ...
У него довольно крутая кривая обучения, поэтому, если у вас нет времени, вы планируете много разрабатывать в WPF / SL, иметь опытных дизайнеров в Blend, чувствовать необходимость написания тестового кода для вашего пользовательского интерфейса или иным образом рассчитывать на годы обслуживания для вашего проект - это может не окупиться.
Не так много дизайнеров знают Blend, не все проекты заслуживают того, чтобы сосредоточить автоматизированное тестирование на уровне представления, так как в любом случае его нужно тестировать вручную, и именно так вы найдете наиболее важные ошибки, а не тестирование своих виртуальных машин.
Это действительно инвестиции. Сначала вы должны понять основы WPF / SL и XAML, а затем выяснить способы правильного выполнения привязок, в некотором порядке подключиться к vms, получить правильное командование, в большинстве случаев выбрать структуру, которая может быть проблематичным из-за лицензирования, создайте библиотеку sippets для эффективного кодирования, только чтобы обнаружить, что платформа не всегда хорошо работает с привязками и требует создания библиотеки поведений, которая дает вам то, что вам нужно.
В целом, хотя - если вы преодолеете все препятствия и станете достаточно опытным в шаблоне - все это окупится ясностью, ремонтопригодностью и ... Хвастовством прав? :)
источник
Я много лет работал программистом на WPF / Silverlight, создавая огромные приложения, такие как торговые системы, для MVVM.
Для меня, с годами, я узнал, что строгий MVVM ест время и стоит денег. Под строгим я подразумеваю такие правила, как «нет кода позади».
Невозможно ни в чем, кроме самого базового приложения для создания форм / баз данных, не иметь кода позади.
В первый день ваш дизайнер определит что-то, что невозможно со стандартными элементами управления, поэтому вы должны создать ряд пользовательских элементов управления или обернуть существующие элементы управления для поддержки парадигмы взаимодействия при работе с MVVM.
Я написал все виды элементов управления Swish UI, используя математику, инерцию, жесты и т. Д. И его тяжелую работу.
Но это весь код, он просто не в поле зрения. Вы должны обрабатывать нажатия кнопок, прокрутку, перетаскивание и т. Д., Но все это красиво упаковано в набор элементов управления, что каким-то образом делает этот код позади.
Зачастую проще просто написать код-сзади и умный интерфейс в представлении, а не создавать набор элементов управления просто ради этого.
Цель MVVM - отделить прикладную / бизнес-логику от логики пользовательского интерфейса. Система привязки и MVVM - хороший способ сделать это.
Другие поставленные цели, такие как конструктор XAML на одной консоли, программист на C # с другой, одна работает в Blend, другая - в VS, - заблуждение.
Возможность быстро перепроектировать пользовательский интерфейс - еще одна ошибка. Этого никогда не бывает, его преждевременная оптимизация; любая серьезная переделка требует большой работы с моделями представлений. Тонкая настройка - это одно, но быстрые изменения пользовательского интерфейса невозможны; модели представлений должны соответствовать парадигме взаимодействия, поэтому связь будет более жесткой, чем вы можете себе представить.
Для меня я использую MVVM, чтобы отделить логику своего приложения (я обычно использую тестируемый контроллер и набор моделей без логического представления), но какой бы код и приемы не использовались, чтобы мой интерфейс выглядел и действовал сексуально, я не Пот это.
Иначе вы в конечном итоге будете ценить свои дизайны, классную анимацию и т. Д. Только потому, что идея о том, как все это создать в MVVM, становится слишком ошеломляющей.
MVVM, как и большинство вещей в жизни, имеет приятное место где-то между двумя крайностями.
Самая важная вещь в дизайне программного обеспечения - это своевременная доставка вашего продукта, выяснение того, какие функции используются, какой пользовательский интерфейс работает хорошо, а не написание красивого кода для продукта, который никто не использует.
источник
Если ваше приложение требует привязки к избыточным объемам данных в режиме реального времени, то MVVM может на самом деле помешать этому, потому что оно вводит абстракции, которые замедляют процесс, и, если мы говорим о WPF / Silverlight / WP7 прямо сейчас, связывание двигатель в настоящее время не так эффективен; хотя улучшения находятся на пути.
MVVM, в его нынешнем виде, также не единственная часть уравнения, которую необходимо учитывать. Чистый MVVM должен поддерживаться инфраструктурой, такой как шаблон «Посредник», чтобы позволить вам взаимодействовать через отключенные модели представления.
Несмотря на мнение Блюча выше, MVVM находится в линии паттернов GoF. Если взглянуть на шаблоны, MVVM является эквивалентом шаблона пассивного представления модели представления, который появился примерно в то же время, что и MVVM. Здесь вы часто будете жаловаться на сложность MVVM просто потому, что не понимают, как его проектировать.
Еще одна область, в которой я обнаружил проблемы с MVVM, - это необходимость включения сторонней технологии, не предназначенной для ее поддержки (например, инфраструктуры UII для MS Dynamics). Время от времени вы должны спросить себя, стоит ли пытаться «взломать» другие технологии, просто работая с MVVM.
Если вы смешиваете и сопоставляете что-то вроде Win Forms в своем решении WPF, то эта часть решения, вероятно, также не будет подходить для MVVM. Я надеюсь, что это даст вам представление о некоторых областях, где MVVM не применим.
источник
Использование MVVM не имеет смысла, когда:
Вот и все. Я не могу придумать, почему бы вам НЕ использовать MVVM при работе с WPF / Silverlight, если вы не тестируете или не отлаживаете что-то в отдельном проекте. Я нахожу шаблон дизайна идеальным для разработки WPF / Silverlight из-за того, как работают привязки XAML.
Весь смысл MVVM в том, что все ваше приложение выполняется в ваших моделях ViewModel, а ваши Views - это просто симпатичный слой, который пользователи могут использовать для взаимодействия с вашими ViewModels. Вы хотите нажать на кнопку, на самом деле вы используете метод ViewModel. Вы хотите изменить страницу, вы фактически изменяете свойство CurrentPage в ViewModel.
Я использую MVVM для всех разработок WPF / Silverlight, даже для небольших, простых одностраничных проектов, хотя то, как я использую MVVM, отличается в зависимости от размера проекта и того, что мне нужно. Однажды, когда я сделал маленькое приложение без MVVM, я пожалел об этом (позже оно было переработано для использования MVVM при добавлении обновления)
источник
Я выполнил некоторую работу для клиента над проектом, который был за кодом с попыткой конвертировать в MVVM, и это было огромной неразберихой. Это не значит, что все проекты с выделенным кодом являются беспорядком. Представления могут привести к ошибке или аварийному завершению Blend, что создает проблемы для дизайнеров.
Я баловался с RoR и почти ничего не делал, когда делал что-то с веб-формами ASP.NET, но когда вышел ASP.NET MVC, я попытался узнать как можно больше, часто используя книги ASP.NET MVC In Action и codecampserver в качестве справочного материала. , Хотя это другой шаблон, я использую многие вещи, которые я узнал из книг In Action при разработке SL / MVVM.
Когда я начал работать с Silverlight, я был удивлен тем, насколько он был голым, и мне казалось, что нужно выбрать одну из множества доступных платформ, чтобы одеть его. Я вижу в этом проблему, когда люди бросают изучать MVVM.
Я начал с превосходного MVVM-Light, который помог мне получить проданную картину. Позже я начал работать с Caliburn Micro, а затем зажегся свет. Для меня Caliburn Micro похож на использование ASP.NET MVC поверх ASP.NET Webforms. Таким образом, даже для небольших примеров приложений я создаю проект NuGet CM, и я не работаю. Я следую первому подходу к ViewModel и сохраняю свои представления немыми и легкими для работы в Blend. Мои виртуальные машины могут быть проверены, если вы в этом разбираетесь, а с помощью CM довольно легко переключаться между сложными компоновками экрана.
источник
Вы можете наслаждаться проверкой этой альтернативы. Этот параметр обходит WPF-способ привязки данных, таблиц данных и MVVM. Эта опция больше похожа на старый, простой и надежный подход WinForms designer.cs.
WPF Composites
http://wpfcomposites.codeplex.com/
Здесь сжатый код C # для WPF создается путем наложения простой матрицы поверх пользовательского интерфейса с помощью композитов на основе сетки. Если современный пользовательский интерфейс XAML содержит только несколько текстовых меток и список фотографий, почему это нельзя определить с помощью простой строки кода: grid.AddText (guid, координата x, координата y)? Обратите внимание, что это не на холсте, но все еще в контейнерах WPF: сетка, док-панель и т. Д. WPF чрезвычайно мощный. Этот подход просто использует это.
Разработчики обычно не возражают против матриц и индексов. Начните с общего уровня контейнеров, определяемого GUID объектов передачи данных (DTO) или POCO, затем дополните эти контейнеры с ключами более мелкой матрицей потенциальных строк и столбцов внутри?
Приведенный выше проект codeplex представляет этот подход, начиная с элемента управления ListBox, но расширяет его и охватывает все составные элементы управления WPF. Например, каждый listboxitem представляет собой составной объект, добавленный с GUID (составной объект связывает один-к-одному с классом), тогда внутри этого элемента есть Grid, на котором дочерние элементы пользовательского интерфейса (дочерние элементы привязывают один-к-одному к свойствам в классе) могут быть добавлены по желанию через код позади. Дети могут быть текстовыми блоками или изображениями.
Идея состоит в том, чтобы использовать индексы и четко определенную структуру Элемента пользовательского интерфейса (она заставляет тематический ListBox PresentationFramework.Aero в качестве основы для начала) вместо шаблонов данных. Этот новый подход преднамеренно ограничивает то, что может быть сделано, но при этом дает краткий, надежный код C #, который интуитивно понятен. Нет необходимости искать решения для шаблонов управления для стилизации полосы прокрутки или загромождать решение несколькими шаблонами данных для простых задач.
источник
MVVM основан в основном на пользовательском интерфейсе, который я использую. Так что с чем-то вроде WPF или Silverlight, у которого есть парадигма, основанная на привязке к текстовому тексту, этот текстовый текст всегда можно назвать моделью представления.
Поэтому вопрос для меня заключается в том, когда вы создаете большой толстый отдельный класс, который является моделью представления для этого элемента управления / окна / приложения, и когда вы можете избежать использования уже созданных объектов.
Итак, у нас есть классический вопрос о добавлении слоя абстракции. VM собирается добавить вес, инерцию и структуру к проекту. Это будет легче строить, но сложнее менять и дольше строить. Ни одна из этих вещей не поддается количественной оценке.
Для дешевого ответа MVVM не подходит для приложений командной строки или веб-служб :)
источник