Зачем ставить бизнес-логику в модель? Что происходит, когда у меня несколько типов хранилищ?


70

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

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

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

И если я хочу другое представление, я должен переписать и представление, и контроллер.

Может кто-нибудь объяснить, почему это так или я где-то ошибся?

Ответы:


69

Ответ ЭльЮсубова главным образом прибивает его, логика предметной области должна входить в модель, а логика приложения - в контроллер.

Два уточнения:

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

4
Большинство MVC-фреймворков смешивают все модели хранилища / базы данных с моделью, чтобы упростить хранение ваших моделей (часто путем расширения класса моделей фреймворков). Это, вероятно, источник путаницы. Технически код модели, который вы пишете, должен быть реальной моделью (уровень домена), тогда как код, предоставляемый платформой, должен иметь дело с хранилищем (уровень персистентности). Например, что-то вроде User.find (...) (с пользователем, являющимся моделью) работает, потому что инфраструктура реализовала шаблон хранилища как часть модели.
Waquo

3
View-Controller-Model-Storage является общим принципом (хотя отношения между M, V и C должны быть визуализированы в виде треугольника). Когда ваш фреймворк смешивает хранилище в свою «модель», он работает примерно так: View-Controller- (модель наследует хранилище от фреймворка).
Waquo

2
View-Controller-Model-Storage довольно сырой, потому что он не должен быть плоским. Например, когда контроллер делает что-то вроде User.find (...) для получения модели, он запрашивает уровень хранения напрямую, а не проходит через уровень домена.
Waquo

2
В архитектурах с более тщательным наслоением это будет что-то вроде UserRepository.find (). Под «моделью» я понимал класс «модель», предоставляемый фреймворком, от которого вы наследуете. User-объект, возвращаемый User.find (), является моделью пользователя в том смысле, что кто-то моделировал, что такое пользователь, как он себя ведет ...
Waquo

1
Бизнес-логика @flipdoubt - это любая логика, которую следует придерживаться, если вы перенеслись с mvc на приложение uwp.
Энди

23

Вы и большая часть мира программирования, кажется, неправильно понимаете, какова роль частей MVC. Короче, это:

Модель = логика домена

Вид = логика вывода

Контроллер = логика ввода

Это означает, что модель отвечает за всю бизнес-логику: все, что связано с рисованием виджетов на экране, управлением принтером, выводом данных в виде HTML, синтаксическим анализом HTTP-запросов и т. Д., Не относится к модели.

Тем не менее, многие современные так называемые "MVC" фреймворки на самом деле вообще не делают MVC или неправильно маркируют свои части. Довольно часто то, что называется «моделью», является постоянным уровнем модели, в то время как бизнес-логика находится в том, что они называют «контроллером»; Фактический контроллер, как правило, представляет собой просто центральную точку входа с таблицей маршрутизации и небольшим количеством кода в отдельных «контроллерах», чтобы распределять входные данные, которые они получают, в правильные бизнес-процессы. То, что эти фреймворки называют «представлением», на самом деле представляет собой всего понемногу: некоторую логику представления (View), немного обработки и проверки ввода (Controller) и еще немного бизнес-логики (Model). Львиная доля фактического представления обычно называется «шаблонами».

Вы также можете прочитать о многоуровневой архитектуре; где MVC является односторонним (поток Controller -> Model -> View), Multi-Tier - двусторонним (Presentation -> Logic -> Data -> Logic -> Presentation), и довольно много фреймворки, которые претендуют на то, чтобы делать MVC, фактически делают трехуровневую, переназначая презентацию в представление, логику в контроллер и данные в модель.


2
Я полагаю, что вы искажаете модель («логика модели = предметной области»), на мой взгляд, это скорее сосуд для заполнения данными, которые затем отображаются с использованием представления в чистейшей форме шаблона MVC. Конечно, в действительно простых случаях использования вы можете рассматривать это как «доменную логику», но я бы сказал, что большинство существующих систем перерастет это очень быстро. Лучше разделить «доменную логику» на отдельный уровень / класс, например уровень обслуживания.
А. Мюррей

@ A.Murray: Конечно, модель не обязательно должна быть одним монолитным блоком кода, и разделение ее на постоянство, структуры данных и доменную логику обычно имеет большой смысл. Тем не менее, MVC группирует эти три проблемы вместе в модели. В любом случае, когда ваши контроллеры и представления содержат доменную логику, это уже не настоящий MVC.
tdammers

@tdammers, мне нравится аккуратность твоего ответа и его внимание к логике. По вашему мнению, к чему относятся такие приложения, как сохранение и обработка транзакций? Похоже, MVC должен быть четырехбуквенным аббревиатурой, как MVCS, где S для обслуживания.
легкое сомнение

15

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

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

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

ОБНОВИТЬ

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

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

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


Похоже, вы описываете ублюдка MVC и MVVM, который имеет как контроллеры, так и модели представления. Кроме того, я думаю, что архитектура, которую вы описываете, может быть немного тяжелой для нужд ОП.
Waquo

честно говоря, мне больше нравится ответ Вако. Главным образом потому, что я понятия не имею, что вы имеете в виду под «службами приложений». Не могли бы вы объяснить этот термин? Мой GoogleFU здесь не работает, как кажется.
Штеффен Винклер

1
@ Я согласен, что предложенная архитектура может быть излишней, однако это следует учитывать. Я не упомянул MVVM, который является просто еще одним способом реализации уровня представления. Службы приложений применяются независимо от того, используете ли вы MVC или MVVM, и ничто из того, что я предложил, не указывает на какую-либо их комбинацию.
eulerfx

1

Зависит от того, что вы подразумеваете под бизнес-логикой. Любая «логика», которая придает смысл содержанию модели, должна быть в модели. В связанном вопросе ответ с наибольшим количеством голосов, кажется, определяет «бизнес-логику» как что-либо, касающееся данных; это имеет смысл с точки зрения того, что данные бизнеса - это его бизнес!

Однажды я увидел пример создателя Rails (я думаю), который продолжал заниматься именно этим - не вкладывая в модель «бизнес-логику». Его примером был класс контроллера и метод для регистрации приложения и входа в систему - предоставленный пароль в виде открытого текста был зашифрован перед вставкой или запросом к модели (базе данных).

Я не могу придумать лучшего примера чего-то, что не является логикой контроллера и принадлежит непосредственно модели.

Модель могла бы быть интерфейсом к множеству хранилищ данных, облегчая проблемы переносимости. Именно здесь можно найти путаницу по поводу того, является ли интерфейс модели «контроллером».

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

Раздел GoF «Шаблоны проектирования» на MVC, в общих чертах:

Триада классов MVC используется для создания пользовательских интерфейсов в Smalltalk-80. Модель - это объект приложения, представление - это экранное представление, а контроллер определяет, как пользовательский интерфейс реагирует на ввод данных пользователем. MVC разделяет представления и модели, устанавливая между ними протокол подписки / уведомления. Следующая диаграмма показывает модель и три вида. Мы упустили контроллеры для простоты.

MVC это все о пользовательских интерфейсах. Основное внимание уделяется модели и представлению - определение и отображение данных. Обратите внимание на «протокол подписки / уведомления» - сюда входит ваш контроллер. Вы можете создавать все представления, которые вам нужны; до тех пор, пока они придерживаются протокола, вам никогда не придется прикасаться к модели или контроллеру.

Если вы говорите конкретно о веб-разработке, IMHO, многие популярные веб-фреймворки бывают быстрыми и свободными с термином MVC и определениями его компонентов.


Я разработчик на C # / Java (там всего несколько проектов). Кажется, я неправильно понял, что делает модель. Внедрение «бизнес-логики» в контроллер действительно было лишь последствием (мой ход мыслей пошел «хорошо, у меня есть модель для данных (читай: подключение / хранение базы данных), поэтому моя бизнес-логика должна войти в контроллер, потому что Я должен применить его перед сохранением данных в базе данных ». Просто нужно переместить все на один уровень вниз от контроллера. На самом деле, это решает проблему, с которой я столкнулся (поддержка MySQL и MSSQL в одной программе)
Steffen Winkler

0

Почему бы вам не ввести уровень обслуживания?

Тогда ваш контроллер станет более компактным и более читаемым, тогда все ваши функции контроллера будут чистыми действиями.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.