Зачем использовать MVVM?

Хорошо, я смотрел шаблон MVVM, и каждый раз, когда я ранее пытался изучить его, я отказался от нескольких причин:

  1. Ненужное кодирование с длинным ветром
  2. Нет очевидных преимуществ для кодеров (в моем офисе нет дизайнеров). В настоящее время я только скоро буду другим кодером)
  3. Не так много ресурсов / документации о передовом опыте! (Или, по крайней мере, трудно найти)
  4. Не могу придумать ни одного сценария, где это выгодно.

Я собираюсь снова отказаться от него, и подумал, что попрошу, если кто-то ответит на вышеупомянутые причины.

Я, честно говоря, не вижу преимущества использования этого для одиночного / партнерского кодирования. Даже в сложных проектах с 10-ю windowsми. Для меня DataSet является достаточно хорошим представлением и привязкой, как в ответе Брент следующим вопросом

Может ли кто-нибудь показать пример того, где использование шаблона MVVM может быть сохранено по сравнению с XAML DataBinding.

В настоящий момент в XAML выполняется 100% привязки. И поэтому я не вижу смысла VM как своего лишнего кода, за которым мне нужно писать и зависеть.

РЕДАКТИРОВАТЬ:
Проведя дневное исследование MVVM, я наконец нашел что-то, что заставило меня осознать истинную выгоду от этого ответа .

Резюме

  • Использование всех шаблонов является ситуационным, и преимущество (если оно есть) всегда кроется в уменьшенной сложности.
  • MVVM помогает нам распределять обязанности между classами в приложении GUI.
  • ViewModel проектирует данные из Модели в формат, который соответствует представлению.
  • Для тривиальных проектов MVVM не требуется. Достаточно использовать только View.
  • Для простых проектов разделение ViewModel / Model может быть ненужным, и достаточно просто использовать модель и представление.
  • Модель и ViewModel не должны существовать с самого начала и могут быть введены, когда они необходимы.

Когда использовать шаблоны и когда их избегать

Для достаточно простого приложения каждый шаблон дизайна является излишним. Предположим, вы пишете приложение GUI, которое отображает одну кнопку, которая при нажатии показывает «Hello world». В этом случае шаблоны проектирования, такие как MVC, MVP, MVVM, все добавляют большую сложность, не добавляя при этом никакой ценности.

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

Для объяснения знакомой и незнакомой сложности возьмите следующие 2 последовательности символов:

  • “D. € |? Ré% DFA с”
  • “CorrectHorseBatteryStaple”

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

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

MVVM

Тем не менее, давайте перейдем к теме MVVM с помощью примера. MVVM направляет нас, как распределять обязанности между classами в приложении GUI (или между слоями – подробнее об этом позже), с целью иметь небольшое количество classов, сохраняя при этом количество обязанностей на class небольшим и четко определенным.

«Правильный» MVVM предполагает, по крайней мере, умеренно сложное приложение, которое имеет дело с данными, которые он получает от «где-то». Он может получать данные из базы данных, файла, веб-службы или из множества других источников.

пример

В нашем примере у нас есть 2 classа View и Model , но без ViewModel . Model обертывает csv-файл, который он читает при запуске, и сохраняет, когда приложение отключается, со всеми изменениями, внесенными пользователем в данные. Класс View – это class Window, который отображает данные из Model в таблице и позволяет пользователю редактировать данные. Содержимое csv может выглядеть примерно так:

 ID, Name, Price 1, Stick, 5$ 2, Big Box, 10$ 3, Wheel, 20$ 4, Bottle, 3$ 

Новые требования: Показать цену в евро

Теперь нас попросят внести изменения в наше приложение. Данные состоят из двухмерной сетки, которая уже имеет столбец «цена», содержащий цену в долларах США. Нам нужно добавить новый столбец, который показывает цены в евро в дополнение к долларам США, исходя из предопределенного обменного курса. Формат csv-файла не должен изменяться, поскольку другие приложения работают с одним и тем же файлом, и эти другие приложения не под нашим контролем.

Возможное решение состоит в том, чтобы просто добавить новый столбец в class Model . Это не лучшее решение, потому что Model сохраняет все данные, которые она предоставляет в csv, – и мы не хотим, чтобы новый столбец евро в CSV. Таким образом, изменение Model было бы нетривиальным, и было бы сложнее описать, что делает class Model, что является запахом кода .

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

Представление ViewModel

В приложении нет ViewModel так как до сих пор Model представляет данные точно так, как это требуется Csv, что также необходимо для View . При наличии ViewModel между ними была бы добавлена ​​сложность без цели. Но теперь, когда Model больше не представляет данные в том виде, в котором она нуждается, мы пишем ViewModel . ViewModel проектирует данные Model таким образом, что View может быть простым. Раньше class View подписывался на class Model . Теперь новый class ViewModel подписывается на class Model и предоставляет данные Model для View – с дополнительным столбцом, отображающим цену в евро. View больше не знает Model , теперь он знает только ViewModel , который с точки View выглядит так же, как и в Model , за исключением того, что открытые данные содержат новый столбец только для чтения.

Новые требования: различный способ форматирования данных

Следующим запросом клиента является то, что мы не должны отображать данные в виде строк в таблице, а вместо этого отображать информацию о каждом элементе (aka row) в виде карточки / коробки и отображать 20 полей на экране в сетке 4×5, отображая 20 коробки за раз. Поскольку мы придерживаемся логики представления Simple, мы просто полностью заменяем View на новый class, который делает по желанию клиента. Конечно, есть еще один клиент, который предпочел старый View , поэтому нам теперь нужно поддерживать оба. Потому что вся общая бизнес-логика уже присутствует в ViewModel что не является проблемой. Таким образом, мы можем решить это, переименовав class View в TableView и CardView новый class CardView который отображает данные в формате карты. Нам также придется написать некоторый код клея, который может быть oneliner в функции запуска.

Новые требования: динамический обменный курс

Следующий запрос клиента заключается в том, что мы вытягиваем обменный курс из Интернета, а не используя предопределенный обменный курс. Это тот момент, когда мы пересматриваем предыдущее заявление о «слоях». Мы не меняем наш Model class, чтобы обеспечить обменный курс. Вместо этого мы пишем (или находим) совершенно независимый дополнительный class, который обеспечивает обменный курс. Этот новый class становится частью модельного слоя, и наша ViewModel объединяет информацию о модели csv-модели и модели обменного курса, которую она представляет в View . Для этого изменения не нужно даже трогать старый class Model и class View. Ну, нам нужно переименовать class Model в CsvModel и мы вызываем новый class ExchangeRateModel .

Если бы мы не представили ViewModel, когда мы это сделали, но вместо этого ждали до сих пор, то объем работы по представлению ViewModel теперь будет выше, потому что нам нужно удалить значительную функциональность как из View и из Model и переместите функциональность в ViewModel .

Послесловие по модулям

Основная цель MVVM заключается не в том, что код в Модели и ViewModel может быть помещен в Unit Test. Основной целью MVVM является то, что код разбивается на classы с небольшим количеством четко определенных обязанностей. Одним из нескольких преимуществ наличия кода, состоящего из classов с небольшим количеством четко определенных обязанностей, является то, что его легче поместить в Unit Test. Гораздо больший выигрыш в том, что код легче понять, сохранить и изменить.

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

Последующие действия: Шаблоны и лучшие практики фактически замедляют первоначальное развитие, и это часто трудно продать руководству и технике. Окупаемость (ROI в терминах бизнес-classа) исходит из хорошо структурированного кода, который фактически поддерживается, масштабируется и расширяется.

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

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

Это помогает вам разделять графический интерфейс и программную логику; их смешивание может привести к очень тяжелому обслуживанию приложений, особенно когда ваш проект растет со временем.

Отсюда :

Почему вы, как разработчик, даже заботитесь о шаблоне Model-View-ViewModel? Существует ряд преимуществ, которые этот шаблон приносит как для разработки WPF, так и для Silverlight. Прежде чем продолжить, спросите себя:

  • Вам нужно поделиться проектом с дизайнером и иметь гибкость для проектных работ и разработок, которые должны произойти почти одновременно?
  • Вам требуется тщательное тестирование модhive для ваших решений?
  • Важно ли для вас использовать повторно используемые компоненты как внутри, так и внутри проектов в вашей организации?
  • Вам нужна дополнительная гибкость для изменения пользовательского интерфейса без необходимости реорганизации другой логики в базе кода?

Если вы ответили «да» на любой из этих вопросов, это лишь некоторые из преимуществ, которые может использовать модель MVVM для вашего проекта.

  • С дизайнерами проще работать (не программисты, просто люди, использующие Blend)
  • Код можно тестировать (модульные тесты)
  • Гораздо проще изменить вид, не вникая в остальную часть кода
  • Пока вы разрабатываете пользовательский интерфейс, вы можете имитировать модель и разработать свой интерфейс без реального обслуживания (только используя макетные данные из модели). Затем вы просто флип и подключитесь к службе.

Есть много хороших вещей о MVVM, но, возможно, самое важное – это возможность протестировать ваш код (модульное тестирование ViewModels).

Отсутствие связи между view и viewmodel действительно помогает ослаблению связи. Очень легко повторно использовать компоненты, которые вы кодируете.

Из статьи Джоша Смита о MVVM :

В дополнение к функциям WPF (и Silverlight 2), которые делают MVVM естественным способом структурирования приложения, шаблон также популярен, потому что classы ViewModel легко тестируются на единицу. Когда логика взаимодействия приложения находится в наборе classов ViewModel, вы можете легко написать код, который его проверяет. В некотором смысле, Views и модульные тесты – это всего лишь два разных типа пользователей ViewModel. Наличие набора тестов для ViewModels приложения обеспечивает бесплатное и быстрое регрессионное тестирование, что помогает снизить затраты на поддержание приложения с течением времени.

Для меня это самая важная причина использования MVVM.

Раньше у меня были бы элементы управления, в которых были объединены вид и viewmodel. Но представление, по сути, имеет мыши и клавиатурные события в качестве входных данных, а рисованные пиксели – как выходные. Как вы тестируете что-то подобное? MVVM устраняет эту проблему, поскольку она отделяет непроверенный вид от проверяемой модели просмотра и удерживает слой вида как можно более тонким.

Прочтите введение в MVVM в этой статье

В 2005 году Джон Госсман, в настоящее время один из разработчиков WPF и Silverlight в Microsoft, представил в своем блоге шаблон Model-View-ViewModel (MVVM). MVVM идентичен модели представления Фаулера, поскольку оба шаблона имеют абстракцию представления, содержащего состояние и поведение View. Фаулер представил презентационную модель как средство создания независимой от пользовательского интерфейса абстракции представления, тогда как Gossman представил MVVM как стандартизованный способ использовать основные функции WPF для упрощения создания пользовательских интерфейсов. В этом смысле я считаю, что MVVM является специализацией более общего шаблона PM, специально разработанного для платформ WPF и Silverlight.

..

В отличие от Presenter в MVP, ViewModel не нуждается в ссылке на представление. Представление привязывается к свойствам в ViewModel, которое, в свою очередь, предоставляет данные, содержащиеся в объектах модели, и другое состояние, специфичное для представления. Связи между представлением и ViewModel просты в построении, потому что объект ViewModel задается как DataContext представления. Если значения свойства в ViewModel изменяются, эти новые значения автоматически распространяются на представление через привязку данных. Когда пользователь нажимает кнопку в представлении, команда в ViewModel выполняется для выполнения запрошенного действия. ViewModel, никогда не View, выполняет все изменения, внесенные в данные модели. Классы представления не имеют представления о том, что classы моделей существуют, а ViewModel и модель не знают о представлении. Фактически, модель полностью не обращает внимания на то, что ViewModel и представление существуют. Это очень слабо связанный дизайн, который во многих отношениях выплачивает дивиденды, как вы скоро увидите.

Также в статье объясняется, почему использовать эти шаблоны gui:

Нет необходимости и контрпродуктивно использовать шаблоны проектирования в простом «Привет, мир!». программа. Любой компетентный разработчик может сразу понять несколько строк кода. Однако по мере увеличения количества функций в программе количество строк кода и движущихся частей соответственно увеличивается. В конце концов, сложность системы и повторяющиеся проблемы, которые она содержит, побуждают разработчиков организовывать свой код таким образом, что его легче осмыслить, обсудить, расширить и устранить неполадки. Мы уменьшаем когнитивный хаос сложной системы, применяя известные имена к определенным объектам в исходном коде. Мы определяем имя для применения к fragmentу кода, рассматривая его функциональную роль в системе.

Разработчики часто намеренно структурируют свой код в соответствии с шаблоном проектирования, в отличие от того, чтобы позволить шаблонам проявляться органично. В любом подходе нет ничего плохого, но в этой статье я рассматриваю преимущества явного использования MVVM как архитектуры приложения WPF. Имена некоторых classов include в себя известные термины из шаблона MVVM, такие как завершение «ViewModel», если class является абстракцией представления. Такой подход помогает избежать когнитивного хаоса, упомянутого ранее. Вместо этого вы можете счастливо существовать в состоянии контролируемого хаоса, что является естественным состоянием дел в большинстве профессиональных проектов разработки программного обеспечения!

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

  1. Я активно использую RelayCommand из Фонда MVVM Джоша Смита. Это значительно упрощает привязку от View to ViewModel через команды.

  2. Я использую AOP для облегчения боли при внедрении INotifyPropertyChanged. В настоящее время я использую Postsharp, хотя я считаю, что есть и другие инструменты, которые могут это сделать. Если бы я этого не обнаружил, я бы, наверное, сейчас отказался бы, так как код шаблона для его реализации вручную действительно меня подшучивал.

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

    • Это то, что я знаю, как это сделать

    • Это то, что мне нужно сделать

Когда вы начинаете структурировать свой код таким образом и используете инструменты, которые упрощают привязку зависимостей (на выбор из широкого спектра рамок IoC), я нашел, что это облегчает некоторую неловкость MVVM, поскольку вы можете уменьшить код шаблона, связанный с введением моделей в ViewModels, и найти различные View Services (такие как отображение диалоговых окон файлов) для ваших ViewModels.

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


Чтобы ответить на вопрос об INotifyPropertyChanged через Postsharp, я использую Aspect, основанный на примере здесь . Я настроил его немного для моего использования, но это дает вам суть. При этом я просто отмечаю class [NotifyPropertyChanged], и все общедоступные свойства будут иметь шаблон, реализованный в их сеттерах (даже если они являются авто-сетью свойств). Мне кажется, что он намного чище, поскольку мне больше не нужно беспокоиться о том, хочу ли я потратить время на то, чтобы class реализовал INotifyPropertyChanged. Я могу просто добавить атрибут и сделать с ним.

Я согласен с тем, что использование MVVM придает больше веса нашим плечам, написав рудный код, но посмотрите на яркую сторону, где все изолировано, а если вы дизайнер, вы можете проектировать свою программу, а другие могут ее кодировать для вас, а другая делает базу данных слой для вас, посмотрите, как поддерживаемые среды вы будете особенно в крупных корпоративных приложениях, если вы не будете использовать MVVM, тогда обслуживание почти убивает … Я сам использовал его при разработке ERP-решения, теперь обслуживание довольно прямолинейно, потому что этого уровня изоляции

Вы будете счастливы в долгосрочной перспективе, если вы используете шаблон, подобный MVVM, по всем причинам, опубликованным другими пользователями. Помните, что вам не нужно следовать требованиям шаблона до слова, просто убедитесь, что у вас есть хорошее разделение между вашим окном (View) и вашей логикой (код-сзади).

Преимущества MVVM

  1. Снижение сложности.
  2. Изоляция проектирования и разработки.
  3. Внедрение зависимости.
  4. Главным преимуществом является то, что у вас есть структурированное приложение Windows Phone с поддержкой MVVM и вы хотите разработать его для Windows Metro Desktop. Единственное, что вы хотите сконцентрироваться на дизайне, поскольку такая же модель представления может использоваться как есть.

Надеюсь, поможет.

MVVM – это действительно чрезмерный код.

Итак, какие преимущества предоставляет MVVM?

Это всего лишь отвлечение внимания не более. Вы также можете записать логику ViewModel в controller. ViewModel просто отвечает за выполнение преобразования (например, и объект в строку). Используя MVVM, вы используете больше объектно-ориентированного стиля программирования. Записывая логику преобразования в controller, вы используете более функциональный стиль программирования.

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

Просто чтобы понять, почему я упоминаю controller: MVVM также имеет код controllerа. Я понятия не имею, почему существует широкий консенсус, чтобы оставить C.

  • WPF XAML Bindings и CurrentCulture Display
  • В чем разница между Width и ActualWidth в WPF?
  • Введите ключевой обработчик события
  • Имя свойства INotifyPropertyChanged - hardcode vs reflection?
  • Установить цвет выделения выделенного элемента ComboBox
  • Событие ComboBox - SelectionChanged имеет старое значение, а не новое значение
  • Как создать пользовательский хром в wpf?
  • Похоже, что привязки данных не обновляются
  • Используйте Messenger MVVM Light для передачи значений между View Model
  • Выделить всю строку TreeViewItem в WPF
  • Как отобразить другое значение для выпадающего списка значений / выбранного элемента в WPF ComboBox?
  • Давайте будем гением компьютера.