Создание уровня обслуживания для моего приложения MVC?

82

Насколько я понимаю, MVC отделяет определения классов (модель) от представления (представления) с помощью «клея», которым является контроллер. Контроллер должен нести единоличную ответственность и, следовательно, быть тестируемым. ViewModels используются для объединения данных из нескольких сущностей и для «массажа» данных из контроллера для представления.

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

user2062383
источник

Ответы:

126

Обычно я использую уровень обслуживания при разработке приложения ASP.NET MVC. Это похоже на шаблон уровня обслуживания, который Мартин Фаулер обсуждает в « Шаблонах архитектуры корпоративных приложений» . Он инкапсулирует вашу бизнес-логику и делает контроллеры довольно тонкими. В основном контроллеры используют уровень обслуживания для получения моделей предметной области, которые затем преобразуются в модели представления. Я также использую шаблон проектирования единицы работы для обработки транзакций и шаблон проектирования репозитория для инкапсуляции уровня доступа к данным для упрощения модульного тестирования и возможности легко заменять ORM. На этом рисунке показаны типичные слои, которые я использую в приложении MVC.

Архитектура MVC

Уровень обслуживания обозначен на этой диаграмме как «Уровень приложения или домена», потому что я обнаружил, что люди путаются, когда вы используете термин «Уровень обслуживания». Они склонны думать, что это веб-сервис. На самом деле это сборка, которая может использоваться вашей любимой технологией веб-служб, такой как веб-API ASP.NET или WCF, а также в качестве контроллера.

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

Кевин Юнгханс
источник
7
Есть ли хороший пример, реализующий эту методологию?
Animesh
@Animesh, вам нужно просто составить примеры в сети, EF + Code First или шаблон POCO для DAL, T4Scaffolding для создания репозитория и UnitOfWork, Service - это просто координация между DAL и POCO, инкапсулирующая бизнес-логику. Затем контроллер ASP.NET MVC ИЛИ WebApi, который только вызывает уровень сервиса и показывает результаты (ASP.NET MVC) или предоставляет его другому клиенту (ASP.NET WebApi)
riadh gomri
2
Репозиторий и UoW не нужны, правда? По крайней мере, в вашем примере, когда вам нужно использовать только одну технологию базы данных (и это не DDD). Вот почему в EF уже реализованы шаблоны UoW и репозитория.
krypru
1
Я не знаю, как здесь, поскольку мне нравятся пример и графика, но многие онлайн-руководства используют шаблон репозитория без нужды. Они абстрагируются, потому что они могут абстрагироваться без всякой пользы, просто чтобы использовать интерфейс.
джонни
Потрясающе !!! Спасибо @kevin Junghans. Ваш ответ действительно помог мне разработать сложное веб-приложение. Один короткий вопрос: при разработке веб-приложений на основе микросервисов: нужно ли нам реализовывать классы служб или просто классы MVC выполняют свою работу.
codemilan
28

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

 public class MyService : IMyService
 {
     IFirstDependency _firstService;
     ISecondDependency _secondService;

     public MyService(IFirstDependency firstService, ISecondDependency secondService)
     {
     }

     public Result DoStuf(InputDTO)
     {
         // some important logic         
     }
 }

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

В соответствии с репозиториями - мой совет - не использовать их, если вы собираетесь использовать какой-либо современный ORM (NHibernate, EntityFramework), потому что ваша бизнес-логика будет инкапсулирована на уровне обслуживания, а ваша база данных будет уже инкапсулирована с помощью инфраструктуры ORM.

Мариан Бан
источник
4
Я думаю, что проблема с пропуском раздела репозитория и переходом прямо к ORM заключается в том, что ваши классы обслуживания напрямую получат контекст ORM, что означает, что все эти классы в вашей службе будут иметь доступ ко всем таблицам, которые вы вытащили в контекст, а не к каждой службе класс, работающий только с нужными ему таблицами. Вы можете избежать этого, передав DbSet в ctor каждого класса и разрешив это с помощью DI, но у вас могут возникнуть проблемы с этим?
user441521
10

Взгляните на статью из лучших практик MSDN.

Исходный код приложения в статье можно найти здесь .

Эмре Неваеширази
источник
10

Цитата из «Бизнес-логика должна быть в сервисе, а не в модели»? :

В архитектуре MVP / MVC / MVVM / MV * сервисы вообще не существуют. Или, если они это сделают, термин используется для обозначения любого универсального объекта, который может быть введен в модель контроллера или представления. Бизнес-логика заложена в вашей модели. Если вы хотите создать «служебные объекты» для управления сложными операциями, это рассматривается как деталь реализации. К сожалению, многие люди реализуют MVC таким образом, но это считается антипаттерном (модель анемической области), потому что сама модель ничего не делает, это просто набор свойств для пользовательского интерфейса.

Некоторые люди ошибочно думают, что использование метода 100-строчного контроллера и внедрение всего этого в сервис каким-то образом улучшает архитектуру. Это действительно не так; все, что он делает, это добавляет еще один, возможно, ненужный уровень косвенности. Фактически, контроллер все еще выполняет свою работу, он просто делает это через плохо названный «вспомогательный» объект. Я настоятельно рекомендую презентацию Джимми Богарда Wicked Domain Models как наглядный пример того, как превратить анемичную модель предметной области в полезную. Он включает в себя тщательное изучение моделей, которые вы демонстрируете, и то, какие операции действительно допустимы в бизнес-контексте.

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

Похоже, вам нужно что-то вроде шаблона репозитория. Вы можете прочитать об этом здесь:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net- mvc-приложение

Этот ответ здесь также может помочь:

Лучший шаблон репозитория для ASP.NET MVC

mnsr
источник
4
Это гораздо больше, чем просто шаблон репозитория. Услуги находятся в доступе к данным тоже , но не только имхо.
boj