2014-02-20 3 views
2

Я всегда был немного смущен относительно того, что «модель» должна или не должна содержать. Учебники и примеры часто противоречат друг другу. До сих пор я играл в это безопасно, мои модели разоблачали не что иное, как «материал UI», например. свойства для привязки к представлению, плюс логика проверки. Но приемлемо ли иметь в бизнесе другую бизнес-логику?Какова ответственность модели в MVVM?

Предположим, что я хочу управлять механическим насосом через веб-сервис, который обеспечивает методы включения насоса с заданной скоростью и его повторного включения. Мое представление пользовательского интерфейса может включать в себя «on» & кнопки «выключено», а также текстовое поле для установки скорости. Имея это в виду, моя модель может начать так: -

public class Pump 
{ 
    public int Speed { get; set; } 
} 

// The real thing would implement INotifyPropertyChanged, validation, etc. 

это все, модель должна делать, или это приемлемо, чтобы выставить бизнес-логику для включения насоса и выключения - либо в качестве методов для вызова модели или, возможно, даже как ICommands, которые могут быть связаны непосредственно с кнопками вида? Или все это должно быть в представлении-модели?

Редактировать Не знаете, почему downvotes, как я думаю, это был вполне разумный вопрос. Хотя в Интернете есть много руководств и примеров MVVM, они часто предоставляют противоречивые советы относительно того, что происходит, как и ответы, приведенные ниже. Я даже закончил читать электронную книгу «Advanced MVVM» экспертом WPF Джошем Смитом - в книге не упоминалось моделей вообще!

В любом случае, я нашел хороший ресурс here для тех, кто хочет подчинить структуру MVVM. В то время как ссылка выводит вас в документацию для платформы Prism от Microsoft, эта конкретная страница посвящена структуре MVVM с небольшой или отсутствующей спецификацией Prism. Я нашел страницу очень информативной и, по крайней мере, успокоился, подтвердив, что то, что я делал за последние пару лет, было совершенно корректным, то есть иметь модели, которые реализуют INPC и проверку (IDataErrorInfo) , и привязывать эти модели непосредственно к представлению через свойства VM (а не дублировать свойства модели в VM, как некоторые ответы ниже).

ответ

2

Целью модели является модель Ваш домен. Объекты, бизнес-логика, услуги - все это принадлежит модели. Что связывает его с пользовательским интерфейсом, это модель представления.

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

public class PumpService 
{ 
    public void Start() { ... }; 
    public void Stop() { ... }; 
} 

public class PumpControllerViewModel : INotifyPropertyChanged 
{ 
    public PumpControllerViewModel(PumpService service) 
    { 
     StartPump = new Command(() => service.Start()); 
     // ... 
    } 
    public ICommand StartPump { get; private set; } 
    public ICommand StopPump { get; private set; } 
} 

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


Обновление в ответ на вопрос OP

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

Сложность модели здесь неактуальна и да, такой подход включает некоторое дублирование кода (в некоторой степени, хотя).

Если вы сохраните модель простой (DTO/POCO -просты), то все, что вам нужно сделать, это переписать POCO -модели в INPC -view модели. В классах моделей было бы очень мало кода, в то время как VM обрабатывала бы уведомлениями (что касается его роли).

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

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

+0

Я очень согласен с этим Jimmy – AlSki

+0

Спасибо за ответ. Возможно, «насос» был не очень хорошим примером - что, если бы у меня была более сложная модель со многими свойствами, например. клиент? То, как я делал до сих пор, заключается в том, чтобы модель реализовала INPC и выставляла ее в представление через одно свойство в VM, позволяя виду привязываться к свойствам модели (например, «{Binding Customer.Forename» " Вы предлагаете подвергать каждое свойство модели через наблюдаемое свойство на виртуальной машине - не связано ли это с большим количеством дублирования свойств, кода сопоставления и т. Д. –

+1

@AndrewStephens: Я заметил в другом комментарии, что вы упоминаете, что используете свой подход * в течение многих лет * .Это EOT IMO.Если это работает для вас так, как вы это делаете, зачем это менять? В конце концов, это всего лишь ** рекомендация ** (как и большинство материалов в разработке программного обеспечения). Моя команда имела прямо противоположную опыт - наш домен (и модель) вырос до такой степени, что этот подход стал очень проблематичным для решения. Позднее проекты мы пошли на более идиоматический MVVM, и с ним было здорово работать. YMMV. –

0

Ну, на самом деле ... «UI stuff» вы упомянули, должны пойти в ViewModels. Некоторый этого материала может быть и в моделях, и проверка может быть непосредственно в представлениях (плюс привязки и т. Д.).

Я рекомендую прочитать руководство разработчика Prism 4.1 (chapter 5), прямо в первом разделе.

+0

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

+0

@ andrew-stephens: Я понимаю, что вы (мы) не делаем это так плохо в конце концов ... Ответы противоречат: ну и что? Это означает, что у людей разные мнения о том, как все должно быть сделано. Всегда учитывайте конечные цели шаблона (то есть: разделение проблем и ослабление сцепления). На самом деле это практически все модели. Вы предпочли бы, чтобы ViewModel напрямую отображал объект модели или «прокси» (дублировал) большую часть своих свойств (и обязанностей)? Первый вариант имеет больше смысла для меня. Что ты думаешь? – Leandro

+1

Я уже несколько лет использую свой подход и считаю его удовлетворительным (и приятно видеть, что это подкреплено этим руководством Prism!). Основываясь на других ответах здесь, также представляется приемлемым иметь бизнес-логику в модели, которая была моим первоначальным вопросом. В конце концов, я думаю, что ключ к разработке программного обеспечения должен быть прагматичным. –

0
But is it acceptable to have other business logic in a model? 

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

Or should all this be in the view-model? 

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

+0

Возможно, логика устойчивости должна быть в своей собственной модели, но все еще в ** модели **, как видно из MVVM. – Gusdor

+0

@Gusdor ... Я думаю, что настойчивость - это ответственность за инфраструктуру, а не модель/сущность. Если вы имеете в виду модель, как в сервисе или репозитории, то да, я согласен. –

+0

Я действительно имел в виду архитектуру сервиса. Для меня MVVM - это концепция приложения, а не схема управления данными. Все, что не касается ввода пользователем или нажатия пикселей, является моделью imo. – Gusdor

0

Интересно, что в этом случае я хотел бы использовать WebService как Model.

Я думаю, вы также можете путать Model с ViewModel. Обычно пользовательский интерфейс определенно находится на ViewModel, оставляя Model понятным, чтобы выполнить фактическую работу. Например,

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

public class ViewModel 
{ 
    public ICommand StopCommand {get; private set;} 
    // other commands 

    public ViewModel() 
    { 
    StopCommand = new MyCommand(()=> { Speed = 0; }); 
    // other commands 
    } 

    public int Speed 
    { 
    //Using webservice as model 
    get { return WebService.GetSpeed(); } 
    set { WebService.SetSpeed(value); } 
    } 
} 

Существует очень хороший exmaple после этого от Laurent Buyginon создателя MVVMLight, но я не могу найти его. Его где-то в http://blog.galasoft.ch/posts/

Смежные вопросы