Зачем использовать MVVM? - PullRequest
70 голосов
/ 16 апреля 2010

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

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

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

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

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

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

EDIT:
Проведя послеобеденное исследование о MVVM, я наконец-то нашел то, что заставило меня осознать истинные преимущества этого ответа .

Ответы [ 13 ]

86 голосов
/ 11 декабря 2013

Резюме

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

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

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

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

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

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

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

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

MVVM

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

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

* * Пример 1 042

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

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

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

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

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

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

Представляем модель представления

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

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

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

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

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

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

Послесловие о юнит-тестах

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

31 голосов
/ 16 апреля 2010

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

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

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

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

14 голосов
/ 16 апреля 2010

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

6 голосов
/ 16 апреля 2010

С здесь :

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

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

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

5 голосов
/ 16 апреля 2010
  • Работать с дизайнерами проще (не программистами, а просто людьми, использующими Blend)
  • Код тестируемый (модульные тесты)
  • Гораздо проще изменить представление, не вмешиваясь в остальную часть кода
  • Пока вы разрабатываете пользовательский интерфейс, вы можете макетировать модель и разрабатывать свой интерфейс без запуска реального сервиса (просто используя фиктивные данные из модели). Тогда вы просто установите флажок и подключитесь к услуге.
3 голосов
/ 16 апреля 2010

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

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

..

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

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

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

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

3 голосов
/ 16 апреля 2010

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

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

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

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

    • Это то, что я умею делать

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

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

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


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

3 голосов
/ 16 апреля 2010

С Статья Джоша Смита о MVVM :

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

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

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

3 голосов
/ 16 апреля 2010

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

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

2 голосов
/ 30 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...