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





Бизнес-логика действительно должна быть в модели. Вы должны стремиться к толстым моделям, худым контроллерам.
Например, вместо:
public interface IOrderService{
int CalculateTotal(Order order);
}
Я бы предпочел:
public class Order{
int CalculateTotal(ITaxService service){...}
}
Это предполагает, что налог рассчитывается внешней службой, и требует, чтобы ваша модель знала об интерфейсах с вашими внешними службами.
Это сделает ваш контроллер примерно таким:
public class OrdersController{
public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}
public void Show(int id){
ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
}
}
Или что-то вроде того.
Так вы бы ввели службы в свои контроллеры вместо репозиториев? Как в этом случае вступает в силу принцип единицы работы?
Я написал еще кое-что, надеюсь, это имеет больше смысла. Вы можете также прочитать: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Даже если речь идет о Rails, это все еще очень применимо.
Я бы лично назвал репозиторий услугой.
Это определенно своего рода служба, но она предназначена специально для доступа к данным. Это просто условность, которую я использую, а не то, что я конкретно защищаю.
Это старый ответ, но что-то запомнилось мне. Метод CalculateTotal в модели использует ITaxService для выполнения работы. Итак, в таком случае, не является ли фактическая бизнес-логика службы, а не самой моделью?
Я думал, что метод CalculateTotal () что-нибудь сделает с результатом налоговой службы. Например, он суммирует позиции заказа, применяет скидки, а затем рассчитывает налог для состояния адреса заказа.
Решение от AlejandroR лучше. Структура должна быть такой: Контроллер -> Бизнес-сервис -> Единица работы -> Репозиторий данных -> Entity Framework.
Я не согласен, я считаю шаблон репозитория антипаттерном. Вы можете обойтись без сворачивания бизнес-сервиса в модель и просто напрямую использовать единицу работы.
Что плохого в наличии интерфейса для ваших услуг? Должны ли вы действительно получать доступ к объектам домена в контроллерах?
Это сделает вашу модель тесно связанной с ITaxService. Если вы хотите повторно использовать модель в другом проекте или другой DLL, у вас должна быть реализация ITaxService или ссылка, иначе ваша модель будет сломана, что приведет к нарушению принципов SOLID. ITaxService должен иметь ссылку на вашу модель. Таким образом, вы можете повторно использовать свою модель в другом проекте без ссылки на ITaxService.
Я думаю, что вы, ребята, не приняли во внимание тот факт, что существует разница между приложением CRUD и приложением богатого домена. Обычный, старый, MVC обычно используется в приложении CRUD. Поскольку MVC сложно поддерживать и его трудно развить там, где домен большой и содержит несколько бизнес-правил (богатый домен), его нужно адаптировать к чему-то вроде ответа @AlejandroR. Таким образом, оба ответа верны, это зависит только от того, используете ли вы CRUD или riche domain.
Это интересный вопрос.
Я думаю, это интересно, что большое количество примеров приложений MVC на самом деле не соответствует парадигме MVC в том смысле, что действительно полностью помещает «бизнес-логику» в модель. Мартин Фаулер указал, что MVC не является шаблоном в смысле «Банды четырех». Скорее всего, это парадигма, согласно которой программист должен добавлять шаблоны к, если они создают что-то помимо игрушечного приложения.
Итак, краткий ответ заключается в том, что «бизнес-логика» действительно не должна жить в контроллере, поскольку контроллер имеет дополнительную функцию работы с представлением и взаимодействиями с пользователем, и мы хотим создавать объекты только с одной целью.
Более длинный ответ заключается в том, что вам нужно подумать над дизайном уровня вашей модели, прежде чем просто переносить логику с контроллера на модель. Возможно, вы сможете обрабатывать всю логику приложения с помощью REST, и в этом случае конструкция модели должна быть достаточно ясной. Если нет, вы должны знать, какой подход вы собираетесь использовать, чтобы ваша модель не раздувалась.
Вы можете проверить это замечательное руководство Стивена Вальтера, которое показывает Проверка на уровне обслуживания.
Learn how to move your validation logic out of your controller actions and into a separate service layer. In this tutorial, Stephen Walther explains how you can maintain a sharp separation of concerns by isolating your service layer from your controller layer.
Это самый правильный ответ. Я лично выступаю за то, чтобы не предоставлять сервисы контроллеру, а вместо этого использовать концепцию ViewModel, такую как шаблон MVVM. Представьте себе сценарий, в котором вы хотите написать бизнес-приложение с интерфейсом рабочего стола (например, с формами Windows или WPF), а также с веб-интерфейсом. Решение этой проблемы приводит вас к паттерну «тонкий контроллер», который также предлагается здесь. Итог: никогда не помещайте бизнес-логику в модель или контроллер и не помещайте в контроллер ничего, чего у вас тоже нет.
Мне нравится диаграмма, представленная Шаблоны и методы Microsoft. И я верю в пословицу: «Картинка стоит тысячи слов».

Это действительно полезно! Не могли бы вы сказать мне, где на том сайте вы нашли эту диаграмму?
Это из "Реализации на стороне сервера" Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Хорошо, но, скажем, в приложении MVC - куда идет бизнес-логика? Кажется, нам нужен дополнительный сервисный слой или что-то в этом роде ?!
Бизнес-логика не должна содержаться в контроллерах. Контроллеры должны быть максимально тонкими, в идеале следовать скороговорке:
Кроме того, контроллеры могут содержать некоторую прикладную логику.
Итак, где мне разместить свою бизнес-логику? В модели.
Что такое модель? Хороший вопрос. См. Статья Microsoft Patterns and Practices (спасибо AlejandroR за отличную находку). Здесь есть три категории моделей:
Конечно, MVC - это парадигма, которая бывает разных видов. Я описываю здесь MVC, занимающий только верхний уровень, см. эта статья в Википедии
Today, MVC and similar model-view-presenter (MVP) are Separation of Concerns design patterns that apply exclusively to the presentation layer of a larger system. In simple scenarios MVC may represent the primary design of a system, reaching directly into the database; however, in most scenarios the Controller and Model in MVC have a loose dependency on either a Service or Data layer/tier. This is all about Client-Server architecture
Если вы используете инжекторы зависимостей, ваша бизнес-логика перейдет к ним, и, следовательно, вы получите аккуратные и чистые контроллеры.
Ссылка на статью мертва - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… - это копия с archive.org для всех, кому интересно.