Где "уровень бизнес-логики" подходит к приложению MVC?

Во-первых, прежде чем кто-то кричит обмануть, мне было сложно суммировать его в простом названии. Другое название могло бы быть: "В чем разница между моделью домена и моделью MVC?" или "Что такое модель?"

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

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

Возьмем простой пример. AccountController, который включен в проект MVC по умолчанию. Я прочитал несколько мнений о том, что включен код учетной записи плохой дизайн, нарушает SRP и т.д. И т.д. Если кто-то должен был создать "правильную" модель членства для приложения MVC, что бы это было?

Как бы вы отделили службы ASP.NET(поставщик членства, поставщик ролей и т.д.) от модели? Или вы вообще?

Как я вижу, модель должна быть "чистой", возможно, с логикой проверки... но должна быть отделена от бизнес-правил (кроме проверки). Например, допустим, у вас есть бизнес-правило, в котором говорится, что кто-то должен быть отправлен по электронной почте при создании новой учетной записи. На мой взгляд, это действительно не относится к модели. Так где же это?

Кто-нибудь хочет пролить свет на эту проблему?

Ответ 1

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

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

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

Дело в том, что при работе с кредитными карточками - я должен требовать cvv при обработке платежа, но я не могу хранить cvv (это штраф в размере 50 000 долларов США для этого). Но я также хочу, чтобы вы могли редактировать свою кредитную карту - изменение адреса, имени или срока действия. Но вы не собираетесь давать мне номер или cvv при его редактировании, и я, конечно, не собираюсь указывать номер вашей кредитной карты в виде обычного текста на странице. Мой домен имеет эти значения, необходимые для сохранения новой кредитной карты, потому что вы даете их мне, но моя модель редактирования даже не включает номер карты или cvv.

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

На мой взгляд, код контроллера должен быть только кодом, нацеленным на представление. Покажите это, скройте это и т.д. На служебном уровне должна быть установлена ​​бизнес-логика для вашего приложения. Мне нравится иметь все это в одном месте, поэтому легко изменить или настроить бизнес-правило. Уровень репозитория должен быть относительно немым - лишен бизнес-логики и только запрашивать ваши данные и возвращать объекты домена. Отделяя модели представления от модели домена, вы получаете гораздо большую гибкость, когда речь идет о пользовательских правилах проверки. Это также означает, что вам не нужно выгружать каждую часть данных в ваш вид в скрытых полях и нажимать их между клиентом и сервером (или перестраивать его на бэкэнд). В вашей модели представлений будет размещена только информация, относящаяся к представлению, и она может быть настроена так, чтобы иметь bools для логики представления или подсчета или перечисления, так что само представление не загромождено сложными логическими утверждениями типа

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

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

Ответ 2

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

Я считаю, что путаница существует из-за вышеприведенной общепринятой архитектуры, в которой используется модель "anemic domain model" (предположительная) -анти. Я не буду вдаваться в подробности о "анти-шаблонности" модели анемических данных (вы можете посмотреть на мое усилие, чтобы объяснить вещи здесь (Основанный на Java, но релевантный для любого языка)). Но, короче говоря, это означает, что наша модель содержит только данные, а бизнес-логику размещают в службах/менеджерах.

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

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

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

Для парадигмы модели анемичных данных, которая широко принята (для хорошей или плохой), модель будет как уровнем обслуживания, так и вашими объектами данных.

Ответ 3

По-моему,

Модель -

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

Бизнес-логика -

Он должен быть помещен в "Уровень услуг домена", это отдельный слой. Также добавим еще один слой здесь "Application Services".

Службы приложений говорят о слое служб домена, чтобы применить бизнес-логику, а затем, наконец, вернуть модель.

Итак, Контроллер будет запрашивать Application Service for Model, и поток будет выглядеть следующим образом:

    Controller->Application Services(using domain services)->Model

Ответ 4

Шаблон MVC и структура Asp.net не делают различий в отношении модели.

Собственные примеры MS включают классы устойчивости в модели. Ваш вопрос о членстве в модели. Это зависит. Являются ли классы в вашей модели кем-то? Существует ли связь между тем, кто входит в систему и какие данные отображаются? Существует ли фильтрация части данных системы разрешений, которая редактируется? Кто последний обновил или отредактировал объектную часть вашего домена, так как кому-то еще нужно его увидеть или что-то для поддержки бэкэнд?

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

Эти типы вопросов слишком широки и субъективны, но я отвечаю так, что вы и все, кто голосовали за вас, понимаете это.

Ваши требования/сроки/ресурсы все сливаются в вашу системную архитектуру. Даже модель дохода может иметь эффект. Вы также должны рассмотреть образец, на который вы стреляете. DDD сильно отличается от приложений с сохранением как модель, и все промежутки между ними также действительны для определенных приложений. Вы снимаете для тестирования приложения? Все это имеет эффект.