ViewModels и рендеринг

В нескольких примерах проектов я видел, как ViewModels используются для преобразования объектов данных в строки для использования в представлении.

ViewModel обычно имеет конструктор, который получает один параметр — объект данных. Затем конструктор заполнит различные свойства ViewModel (в основном строки и целые числа).

Это предотвращает появление какой-либо сложной логики в представлении.

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

Например, скажем, мое представление пыталось отобразить свойство «Размер» объекта данных, где «Размер» представляет собой число от 1 до 3, представляющее «Малый/Средний/Большой».

Вместо того, чтобы иметь оператор if/switch в моем представлении, у меня был бы просто «SizeString» или что-то подобное в моей ViewModel, а оператор if/switch попадал бы в конструктор ViewModel.

Кто-то не согласен с таким подходом?

Было бы лучше использовать какой-то другой подход, например помощники? И если да, то почему?


person Jonathan    schedule 02.01.2010    source источник


Ответы (2)


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

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

Рассмотрим альтернативу: если не реализовано в ViewModel, то где? Если вы поместите логику куда-то еще, вы получите ViewModel, которая в основном представляет собой просто структуру без логики. Разрешение ViewModel инкапсулировать преобразование/декомпозицию объекта предметной области хорошо соответствует принципу единой ответственности.

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

person Mark Seemann    schedule 02.01.2010
comment
Хорошее объяснение. Причина, по которой я не был уверен в этом, заключалась в том, что я где-то читал, что ViewModels должны быть просто объектами POCO без какой-либо логики. Но ясно, что это не сработает. ViewModels должно быть разрешено содержать логику представления. - person Jonathan; 02.01.2010
comment
POCO не исключает наличия логики :) - person Mark Seemann; 02.01.2010
comment
Хотел написать про SRP, но вы это уже сделали. Как я всегда говорю - тяжело быть одновременно боксером и балериной. :) - person Arnis Lapsa; 02.01.2010
comment
Мы обнаружили, что проще создать ViewModels как POCO, которые соотносят 1-1 с элементами управления/данными представления, а затем поместить всю логику сопоставления/преобразования в отдельные классы сопоставления. Это позволяет лучше повторно использовать простое сопоставление, а также снижает вероятность того, что разработчик начнет помещать в представление более сложные вызовы (единственные вызовы функций, которые мы делаем, относятся к вспомогательным классам Html). - person Beep beep; 03.01.2010
comment
Интересная идея. Я также слышал о дублировании свойств объекта предметной области, а затем использовании такой структуры, как AutoMapper, для автоматического переноса данных из объекта предметной области в ViewModel. - person Jonathan; 03.01.2010

Он преобразует все в строку, потому что все в сети является строкой.

По сути, модель представления должна быть в состоянии «готова к выводу». Если бы сеть была сделана только из чисел - мы бы преобразовали все в целые/десятичные числа.

Вся точка зренияModel - форматировать данные в представляемом виде. В вашем случае - размер перечисления на маленький/средний/большой. Дело не в том, что отделение логики от представлений делает это ценным — это возможность адаптировать ваши данные для Интернета одним способом и в одном месте.


Ответ на комментарий =>

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

person Arnis Lapsa    schedule 02.01.2010
comment
На самом деле я уже реализовал его как Enum, но исключил этот факт, чтобы не усложнять пример. Конечно, если я просто позволю представлению напрямую обращаться к Enum, все равно будет какая-то логика для преобразования его в строку, например: Enum.GetName(...). Поэтому я все же предпочел бы представить свойство в виде строки в ViewModel и позволить ViewModel позаботиться о преобразовании строки перечисления. Вам бы это понравилось? - person Jonathan; 02.01.2010