Должна ли MVVM ViewModel выполнять преобразование / проверку типа? - PullRequest
36 голосов
/ 26 августа 2009

Мы просто входим в MVVM в WPF.

Мы реализовали наши ViewModel с «строго типизированными» свойствами (int, double? И т. Д.), С которыми мы связываемся в представлении.

Преобразование типов работает в основном нормально, поэтому ввод данных достаточно прост. Но мы сталкиваемся с проблемами с проверкой.

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

Все это можно обрабатывать с помощью преобразователей значений, я знаю. Но я видел несколько мнений о том, что обращение вообще не должно быть ответственностью мнения. То, что вводится в представление, является строками, и преобразование, проверка и т. Д. Должны быть ответственностью ViewModel (поэтому аргумент идет).

Если это так, мы должны переписать большинство свойств наших ViewModels в строку и предоставить информацию об ошибке, например, через интерфейс IErrorInfo. Это, безусловно, сделало бы более простой и тонкий XAML в представлении. С другой стороны, преобразование, проверка и т. Д. Будут менее декларативными, явными и гибкими с точки зрения дизайнера View.

Нам кажется, что эти два подхода принципиально различны, поэтому, прежде чем мы решим, мы хотели бы получить некоторые обоснованные мнения SO по этому вопросу.

Итак: должны ли ViewModels предоставлять упрощенный текстовый интерфейс для представления и обрабатывать преобразование внутри? Или свойства ViewModel должны отображать фактические типы данных, оставляя такие обязанности для просмотра для обработки?

Обновление:

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

В частности, мы решили сохранить типизированные свойства ViewModel. Основной причиной этого является гибкость, которую он дает нам при разработке представления, и мощь явного декларативного преобразования / форматирования в XAML.

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

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

Смысл всего этого в том, что, хотя принудительное применение бизнес-правил, безусловно, относится к ViewModel, нам кажется, что простое преобразование и форматирование - это точка зрения. Это может звучать как ересь, но я не думаю, что преобразование типов в представлении вообще нуждается в модульном тестировании (так долго, пока мы тестируем модули самих преобразователей типов).

В целом, отличная дискуссия, ребята, с хорошо сформулированными, обоснованными мнениями. Спасибо.

Ответы [ 5 ]

13 голосов
/ 26 августа 2009

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

Глядя на шаблон MVVM, как я его понимаю, смысл ViewModel состоит в том, чтобы представить данные так, как View может понять без каких-либо предположений о том, как представление будет использовать его. Для примера давайте представим, что мы моделируем скорость автомобиля:

public class CarModel
{
    public int MilesPerHour { get; set; }
}

public class CarViewModel
{
    private CarModel _model;

    public int MilesPerHour
    {
        get { return _model.MilesPerHour; }
        set { _model.MilesPerHour = value; }
    }
}

В приведенном выше примере я выставил свойство как int, поскольку оно есть в модели. Недостатки этого вы перечислили в своем вопросе, но главное преимущество заключается в том, что он дает создателю представления ценную информацию о том, как отображать эти данные. Помните, что мы (как авторы ViewModel) не знаем, как выглядит View. Приняв идею о том, что данные являются целыми, представление может использовать текстовое поле или какой-либо другой элемент управления, который принимает только цифры (например, циферблат) для отображения информации. Если мы говорим, что собираемся отформатировать данные таким образом, чтобы мы предположили, что полезен для просмотра, это отнимает у него эту важную силу.

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

Наконец (и я уверен, что вы это знаете, но для завершения ...) бизнес-логика должна быть выполнена во ViewModel. Если мы решим, что автомобиль не должен превышать 70 миль в час, то ответственность за это не возлагается на точку зрения. Таким образом, у вас все равно останется какой-то поставщик ошибок, но на уровне бизнеса, а не на уровне отображения.


Хорошо, может быть, это не было окончательно ...

Я хотел ответить на комментарии Кента, и мои мысли не вписались в комментарий.

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

Моя точка зрения основана на предположении, что вы должны иметь возможность менять представления, они должны быть мимолетными, которые могут меняться в зависимости от требований к размеру экрана, аппаратному обеспечению, платформе, задержке и среде. Интересным моментом является то, что мне никогда на самом деле не нужна была эта функциональность, и я не видел ничего (кроме доказательства концептуальных приложений), которое когда-либо использовало ее, но если мы примем, что мы не будем использовать ее сейчас или в любой момент указать на будущее, и что каждая ViewModel будет работать с одним и только одним View, тогда мы можем также вернуться к размещению всего кода в файле code-behind и полностью выбросить ViewModel - в конце концов, это так тесно в сочетании, что это может быть тот же класс.

В идеале мне хотелось бы, чтобы ViewModel могла сказать: «это значение является целым числом, оно всегда будет целым числом, и вы можете отобразить его любым способом, который вам нравится. Но вы можете отдать мне все, что угодно, и я» Я сделаю все возможное, чтобы сделать его подходящим, и если я не смогу, я дам вам знать ". По сути, в моем свойстве MilesPerHour должен быть объект int get, но объект set. Таким образом, представления хранят всю информацию, которая, по моему мнению, им нужна, но не нужно беспокоиться о конверсиях или проверке.

8 голосов
/ 26 августа 2009

Абсолютно принадлежит модели представления, по всем обычным причинам, включая:

  • Дизайнеры владеют XAML. Вы хотите, чтобы дизайнеры поняли и реализовали необходимую логику преобразования и проверки типов?
  • Тестируемость. Разве вы не хотите проверить, правильно ли работает логика преобразования и проверки? Гораздо сложнее, если он встроен в представление.

С другой стороны, преобразование, проверка и т. Д. Будут менее декларативными, явными и гибкими с точки зрения дизайнера View

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

5 голосов
/ 26 августа 2009

Если MVVM ViewModel выполняет тип преобразование / проверка

Да .

Модель представления представляет собой слой абстракции между представлением и моделью - идеальное место для выполнения любых преобразований типов (вместо громоздких преобразователей значений). Проверка должна обязательно происходить как часть модели представления.

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

Один конкретный вопрос, который вы подняли:

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

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

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

  • Мы (разработчики) сохраняем здравомыслие (XAML несколько менее многословен)
  • Бизнес-логика (включая проверку) остается в модели представления и может включать тестирование

Удачи!

-Z

5 голосов
/ 26 августа 2009

Это хороший вопрос, и я, безусловно, вижу обе стороны обсуждения.

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

Я не уверен, как бы вы хотели реализовать его, я знаю, что классические элементы управления spinner / NumericUpDown теряют популярность, потому что они не сенсорные, но я не верю, Введение такого элемента управления нарушит чистоту подхода к дизайну или ваших ViewModels. Вы получите номер, который вы можете затем проверить в соответствующем месте, отправить отзыв по номеру IDataErrorInfo, как обычно, и так далее. :) Эта техника позволяет вам получить лучшее из обоих миров без каких-либо реальных недостатков (кроме создания числового элемента управления).

0 голосов
/ 21 августа 2015

Или свойства ViewModel должны представлять фактические типы данных, оставляя такие обязанности для просмотра для обработки?

  1. Преобразование и шаблонов выполняется в View, потому что они оба являются просто преобразованием values, models и viewmodels в controls! Controls доступны только внутри View.

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

Если, скажем, в текстовое поле введено нечисловое значение, связанное с числовым свойством

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

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