MVC 3 - Контроллеры и ViewModels - Что должно содержать большую часть бизнес-логики? - PullRequest
14 голосов
/ 12 сентября 2011

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

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

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

Мой запах кода говорит мне, что это так.Тем не менее, я немного обеспокоен тем, как это будет согласовываться с контроллерами, которые выполняют действия, которые не требуют ViewModels.Проще говоря, действия, которые не требуют передачи Model / ViewModel в View;этот случай происходит с действиями, которые перенаправляют на другие действия.Это означает, что моя бизнес-логика может либо остаться в этом действии, либо я могу разделить эту бизнес-логику на функцию.

Какова лучшая практика здесь?

Ответы [ 4 ]

10 голосов
/ 12 сентября 2011

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

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

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

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

Надеюсь, это поможет.Удачи.

7 голосов
/ 13 сентября 2011

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

Ни один из них.

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

imho Это очень плохая идея.Прежде всего, вы нарушаете несколько принципов SOLID.Объединение всего кода в модель представления затрудняет тестирование.Что если вы хотите использовать некоторую бизнес-логику в другом представлении?Вы дублируете этот код?

Какова лучшая практика здесь?

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

  • «Модель» в MVC - это действительно все, что используется для объединения данных.Это могут быть веб-сервисы, бизнес-уровень, репозитории и т. Д.

  • Представление - это весь код, который генерирует HTML (поскольку речь идет о сети).

  • Контроллер следует считать связующим звеном между моделью и видом.Следовательно, он должен взять информацию из модели и преобразовать ее в нечто, пригодное для использования представлением.

Проблема с этой структурой заключается в том, что довольно просто «просачивать» информацию, относящуюся к слою, вдругие части рисунка.Поэтому Microsoft ввела ViewModel в свою реализацию MVC.

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

<span>@(model.Age == 0 ? "n/a" : model.Age)</span>

вы помещаете этот код в ViewModel и просто вызываете @model.Age.Таким образом, вам не нужно дублировать этот код во всех представлениях, которые используют вашу модель представления.

Ответ на ваш вопрос о ViewModel заключается в том, что он должен содержать только логику, которая используется для правильной визуализации информации из «Модели».

Что касается контроллера, я бы не стал ставитьлюбая бизнес-логика в это тоже.Прежде всего, это очень затрудняет проверку вашей логики.Затем вы добавляете больше обязанностей (и тем самым нарушаете SRP).Единственная логика, которая действительна в контроллере, - это взять информацию из ViewModel и преобразовать ее во что-то, что можно использовать с помощью «Модели», и наоборот.

Надеюсь, что ответ на ваш вопрос.

Обновление

Я бы создал отдельный проект и добавил к нему классы.Затем просто добавьте ссылку из вашего веб-проекта и вызовите эти классы в контроллерах.

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

Autofac может обнаружить ваши услуги для вас (нулевая конфигурация)и внедрить себя в MVC.

Чтобы следовать шаблону разделенного интерфейса, создайте следующие проекты:

  • YourProject.BusinessLayer <- добавьте свои классы сюда </li>
  • YourProject.BusinessLayer.Specification <- Добавьте сюда интерфейсы, которые определяют ваш бизнес-уровень. </li>
  • YourProject.Mvc <- Проект MVC. </li>

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

3 голосов
/ 12 сентября 2011

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

Например:

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

Из Википедии:

ViewModel: ViewModel является «моделью представления», то есть абстракцией представления, которая также служит для привязки данныхмежду видом и моделью.Это можно рассматривать как специализированный аспект того, что будет контроллером (в шаблоне MVC), который действует как механизм связывания / преобразования данных, который изменяет информацию о модели в информацию о представлении и передает команды из представления в модель.ViewModel предоставляет общедоступные свойства, команды и абстракции.Модель представления была уподоблена концептуальному состоянию данных, а не реальному состоянию данных в модели. [7]

1 голос
/ 11 апреля 2013

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

, а затем передать все необходимые данные вашему конструктору viewmodel.(передача Uow в de viewmodel звучит как очень плохо)

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

SomeClass something = Uow.BLGoodName.DoSomeFancyStuff(params ..)
ViewData.model = new ControllerActionViewModel(something);
Return View();
...