Слой службы и структура проекта в ASP.NET MVC 5 без репозитория и шаблонов UoW

Я хотел бы создать хорошее приложение в ASP.NET MVC 5, используя первую концепцию кода EF 6. Я хочу, чтобы он был хорошо спроектирован, т.е. имел, вообще говоря, разделенные уровни представления, логики и данных. Я хочу, чтобы это можно было проверить :)

Вот моя идея и некоторые вопросы, связанные с созданием приложения

Презентационный уровень: это весь мой MVC - модели просмотра (не модели), представления, контроллеры. Я считаю, что проверка должна выполняться где-то еще (на мой взгляд - это часть бизнес-логики), но это довольно удобно для использования атрибутов из пространства имен DataAnnotations в ViewModelds и проверки проверки в контроллере.

Логический уровень: службы — классы со своими интерфейсами для управления бизнес-логикой. Я поместил туда такие функции, как: AddNewPerson(PersonViewModel Person), SendMessageToPerson(...). Они будут использовать контекст БД для выполнения своих действий (есть шанс, что не все из них будут полагаться на контекст). Существует прямая связь между сервисом и базой данных - я имею в виду, что класс сервиса имеет ссылку на контекст. Где мне сделать сопоставление между ViewModel и Model? Слышал, что в сервисе плохое место для этого - может быть, в контроллерах. Я слышал, что служба должна выполнять работу, связанную исключительно с БД. Это правильно? Является ли моя картина сервисного уровня хорошей?

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

Вот мой поток:

Представление‹->Контроллеры (с использованием моделей представления)‹->Сервисы (с использованием моделей)‹->БД.

** Я буду использовать DI в своем проекте.

Что вы думаете о структуре моего проекта?


person WaltLift0    schedule 11.09.2014    source источник


Ответы (2)


Нет причин использовать шаблон единицы работы с Entity Framework, если вам не нужно создавать общий механизм доступа к данным. Вы бы сделали это, только если бы вы были:

  1. с использованием технологии доступа к данным, которая изначально не поддерживает шаблон единицы работы (EF поддерживает)
  2. Хотел иметь возможность поменять местами поставщиков данных когда-нибудь в будущем.. однако это не так просто, как может показаться, поскольку очень сложно НЕ вводить зависимости от конкретных технологий данных даже при использовании единицы работы (возможно, даже ПОТОМУ ЧТО вы есть)... или
  3. Вам нужен способ объединения разрозненных источников данных в атомарную транзакцию.

Если ни один из них не имеет места, вам, скорее всего, не нужна пользовательская единица работы. С другой стороны, репозиторий может быть полезен... но с EF6 также доступны многие преимущества репозитория, поскольку EF6 предоставляет фиктивные интерфейсы для тестирования. Тем не менее, держитесь подальше от универсального репозитория, если это не просто деталь реализации ваших конкретных репозиториев. Предоставление общих репозиториев другим слоям — это огромная утечка абстракции...

Я всегда использую шаблон Repository/Service/Façade, чтобы создать разделение между моими данными и бизнес-слоями (и пользовательским интерфейсом и бизнесом, если уж на то пошло). Он предоставляет удобный способ имитации без необходимости имитировать сам доступ к данным и отделяет вашу логику от специфики, представленной уровнем Linq, используемым EF (Linq является относительно универсальным, но есть вещи, специфичные для EF). интерфейс фасад/репозиторий/сервер разделяет это).

В общем, вы на правильном пути... Однако позвольте мне отметить, что использование атрибутов данных в ваших моделях представления — это хорошо. Это централизует вашу проверку на вашей модели, а не заставляет вас размещать логику проверки повсюду.

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

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

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

person Erik Funkenbusch    schedule 11.09.2014
comment
Спасибо, Эрик. Я вижу вашу точку зрения. Вы упомянули о проверке - я понимаю вашу точку зрения. Что такое репозиторий и фасад в вашем проекте? - person WaltLift0; 12.09.2014
comment
@WaltLift0 — шаблон репозитория — это всего лишь специализированный шаблон фасада. Это помещает вашу реальную реализацию за интерфейс, чтобы отделить ее, чтобы ни одна сторона не знала о другой. - person Erik Funkenbusch; 12.09.2014

Хорошо, давайте проясним некоторые вещи...

Понятие ViewModel (или фактическая формулировка ViewModel) введено Microsoft Мартин Фаулер. На самом деле, ViewModel — это не что иное, как простое class.

На самом деле ваши Views строго типизированы до classes. Период. Чтобы избежать путаницы, была предложена формулировка ViewModel, чтобы помочь людям понять, что

«этот класс будет использоваться вашим представлением»

поэтому мы называем их ViewModel.

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

На самом деле, вы когда-нибудь замечали, почему внутри приложения MVC есть папка Models, а не папка ViewModels?

Кроме того, вы когда-нибудь замечали, что в верхней части представления у вас есть директива @model, а не директива @ viewmodel?

Это потому, что все может быть моделью.

Кстати, для ясности, вы можете удалить (или переименовать) папку Models и создать новую с именем ViewModels, если это поможет.

Независимо от того, что вы делаете, в конечном итоге вы будете называть @model, а не @viewmodel вверху страницы.

Другим подобным примером может быть DTO classes. Классы DTO — это не что иное, как обычные классы, но они имеют суффикс DTO, чтобы помочь людям (программистам) различать все остальные классы (включая модели представления).

В недавнем проекте, над которым я работал, это понятие не было полностью понято командой, поэтому вместо того, чтобы их Views строго типизировали до Models, их Views строго типизировали до DTO classes. В теории и на практике все работало, но вскоре они обнаружили, что у них есть такие свойства, как IsVisible внутри их DTO, когда на самом деле; такие свойства должны принадлежать вашим ViewModel классам, поскольку они используются для логики пользовательского интерфейса.

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

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

Ваш Service Layer не должен иметь представления о том, что такое ViewModel. Он должен только принимать, получать, отправлять и т. д. классы POCO.

Это означает, что из вашего Controller внутри вашего ActionResult, как только ModelState станет Valid, вам нужно преобразовать ваш ViewModel в POCO, который, в свою очередь, будет отправлен методу внутри вашего Service Layer.

Другими словами, я бы использовал/установил пакет Automapper nugget и создал несколько методов расширения, которые преобразовали бы ViewModel в POCO и наоборот (POCO в ViewModel).

Таким образом, ваш метод AddNewPerson() получит объект Person для своего параметра вместо получения параметра PersonViewModel.

Помните, это справедливо только для if and only if ваших Service Layer планов по обслуживанию других вещей...

Если это не так, то не стесняйтесь, чтобы ваши Service Layer получали, отправляли, добавляли и т. д... ViewModels вместо POCO. Это зависит от вас и вашей команды.

Помните, что есть много способов снять шкуру с кошки.

Надеюсь это поможет.

person Vlince    schedule 11.09.2014
comment
Неправильно. Понятие ViewModel было создано Мартином Фаулером, хотя он назвал его моделью представления, и оно определено в его шаблоне модели представления. См. martinfowler.com/eaaDev/PresentationModel.html. Кстати, это называется NuGet, а не самородок. Я упоминаю об этом только потому, что вы кажетесь таким приверженцем номенклатуры. - person Erik Funkenbusch; 12.09.2014
comment
Правильно, французская версия Word, которую я использую, игнорировала ошибку. Спасибо за поправку :-) - person Vlince; 12.09.2014
comment
Спасибо, Влинс. Вы дали мне понять некоторые вопросы. Возвращаясь к различиям между Model и ViewModel. Я думаю, что они имитируют немного разные вещи: Модель - бизнес-объект, ViewModel - выбранные элементы из бизнес-объекта + некоторые дополнительные вещи для конечного пользователя. - person WaltLift0; 12.09.2014