Где «уровень бизнес-логики» вписывается в приложение MVC? - PullRequest
85 голосов
/ 30 декабря 2010

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

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

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

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

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

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

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

Ответы [ 4 ]

69 голосов
/ 30 декабря 2010

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

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

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

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

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

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

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

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

17 голосов
/ 30 декабря 2010

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

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

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

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

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

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

3 голосов
/ 30 декабря 2010

На мой взгляд,

Модель -

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

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

Он должен быть размещен на «уровне доменных служб», это вообще отдельный уровень. Также добавим сюда еще один слой «Службы приложений».

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

Итак, Контроллер запросит Службу Приложений для Модели, и поток будет иметь вид,

    Controller->Application Services(using domain services)->Model
2 голосов
/ 30 декабря 2010

Шаблон MVC и инфраструктура Asp.net не делают различий в том, какой должна быть Модель.

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

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

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

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

...