Навіщо ставити бізнес-логіку в модель? Що відбувається, коли у мене є кілька типів сховища?


70

Я завжди думав, що бізнес-логіка повинна бути в контролері і що контролер, оскільки це "середня" частина, залишається статичним і що модель / вигляд потрібно капсулювати за допомогою інтерфейсів. Таким чином ви можете змінити логіку бізнесу, не впливаючи ні на що інше, запрограмувати кілька Моделей (по одній для кожної бази даних / типу пам’яті) та десятки переглядів (наприклад, для різних платформ).

Тепер я читаю в цьому запитанні, що завжди слід вводити ділову логіку в модель і що контролер глибоко пов'язаний з поданням.

Для мене це насправді не має сенсу, і це означає, що щоразу, коли мені хочеться мати засоби підтримки іншої бази даних / типу зберігання, я повинен переписати всю свою модель, включаючи бізнес-логіку.

І якщо я хочу іншого перегляду, я повинен переписати і перегляд, і контролер.

Може хтось пояснить, чому це так, або якщо я десь помилився?

Відповіді:


69

Відповідь ElYusubov здебільшого вказує на це, логіка домену повинна входити в модель і логіка програми в контролер.

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

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

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

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

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

2
В архітектурах з більш ретельним шаруванням це було б щось на зразок UserRepository.find (). Під "моделлю" я мав на увазі клас "модель", що надається рамкою, від якої ви успадковуєте. User-object, повернутий User.find (), - це модель користувача в тому сенсі, що хтось моделював, що таке користувач, як поводиться користувач ...
Waquo

1
@flipdoubt бізнес-логіка - це будь-яка логіка, яку слід зберігати однаковою, якщо ви перейшли з mvc, щоб сказати, uwp додаток.
Енді

23

Ви і велика частина світу програмування, здається, неправильно розумієте, які ролі частин MVC. Коротше кажучи, це:

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

Вид = логіка виводу

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

Це означає, що модель відповідає за всю логіку бізнесу: все, що стосується малювання віджетів на екрані, керування принтером, виведення даних у вигляді HTML, розбору HTTP-запитів тощо, не належить до моделі.

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

Ви також можете прочитати про багаторівневу архітектуру; де MVC є однобічним (потік Controller -> Model -> View), багаторівнева річ - це двостороння (Презентація -> Логіка -> Дані -> Логіка -> Презентація), і досить багато рамки, які претендують на MVC, насправді роблять трирівневі, відновляючи презентацію для перегляду, логіки до контролера та даних для моделі.


2
Я вважаю, що ви неправильно представляєте Модель ("Модель = логіка домену"), на мій погляд, це більше посудина для сукупності з даними, яка потім надається за допомогою View, в чистому вигляді шаблону MVC. Звичайно, у дуже простих випадках використання ви можете трактувати це як "логіку домену", але я б поручав, що більшість існуючих систем переросте це дуже швидко. Краще розділити "логіку домену" на окремий шар / клас, наприклад, сервісний рівень.
А. Мюррей

@ A.Murray: Звичайно, модель не повинна бути однією монолітною кодовою частиною коду, і розділення її на стійкість, структури даних та доменну логіку зазвичай має багато сенсу. Тим не менш, MVC об'єднує ці три проблеми разом у моделі. У будь-якому випадку, коли ваші контролери та представлення містять логіку домену, це вже не справжній MVC.
tdammers

@tdammers, мені подобається охайність вашої відповіді та її спрямованість на логіку. На вашу думку, куди належать проблеми, пов'язані із застосуванням, такі як наполегливість та обробка транзакцій? Здається, MVC має бути абревіатурою з чотирьох літер, як MVCS, де S призначений для обслуговування.
flipdoubt

15

Щоб по-справжньому ізолювати ділову логіку та зробити її відокремленою від інфраструктури рівня презентації, її слід інкапсулювати службами прикладних програм. Архітектура MVC - це спосіб реалізувати презентаційний рівень, і він повинен залишатися в цій області, делегуючи всю ділову логіку цим службам прикладних програм. Подумайте про моделі перегляду як адаптери між поданням та даними, які потрібно відображати та читати. Контролер опосередковує взаємодію між моделями перегляду, переглядами та службами додатків, які розміщують бізнес-логіку.

Служби прикладних програм реалізують випадки використання бізнесу та відокремлюються від шару презентації, будь то MVC або щось інше. У свою чергу, сервіси додатків можуть розміщувати сценарії транзакцій або дизайн, керований доменом .

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

ОНОВЛЕННЯ

Моя пропозиція заснована на шестикутній архітектурі . У шестикутній архітектурі ваша доменна модель (бізнес-логіка) лежить в основі. Це ядро ​​інкапсульовано прикладними службами, які виконують роль фасаду . Прикладні сервіси - це прості класи, у яких є методи, що відповідають випадкам використання у вашому домені. Для поглибленої дискусії щодо прикладних служб подивіться Служби в дизайні, керованому доменом . Зразок коду містить PurchaseOrderServiceсервіс, який представляє собою додаток для придбання домену. (Зауважте, що служба прикладних програм не передбачає використання дизайну, керованого доменом.)

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

Це рішення, безумовно, має рухомі частини, ніж рішення, яке розміщує ділову логіку в контролері, і ви повинні зважити недоліки та переваги. Причина, яку я пропоную, полягає в тому, що я віддаю перевагу, щоб ділова логіка не була відокремлена від шару презентації, щоб боротися зі складністю. Це стає важливішим у міру зростання програми.


Здається, ви описуєте сволота MVC та MVVM, який має як контролери, так і перегляд моделей. Крім того, я думаю, що архітектура, яку ви описуєте, може бути дещо важкою для потреб ОП.
Вакуо

чесно кажучи, мені більше подобається відповідь Вакуо. Головним чином, тому що я не розумію, що ви маєте на увазі під "прикладними послугами". Чи можете ви пояснити цей термін? Мій GoogleFU тут не працює, як здається.
Стеффен Вінклер

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

1

Залежить від того, що ви маєте на увазі під діловою логікою. Будь-яка "логіка", яка надає значення змісту моделі, повинна бути в моделі. У пов'язаному запитанні найвища відповідь, що визначається, визначає "логіку бізнесу" як будь-що, що стосується даних; це має сенс з точки зору того, що дані бізнесу - це його бізнес!

Я одного разу побачив приклад творця Rails (я думаю), який робив саме так - не вкладаючи "бізнес-логіку" в модель. Його прикладом був клас контролера та метод реєстрації та входу в додаток - наданий пароль в простому тексті був зашифрований перед тим, як вставлятись у нього або запитуватися проти моделі (бази даних).

Я не можу придумати кращого прикладу того, що не є логікою контролера і що безпосередньо належить до моделі.

Ця модель може бути інтерфейсом для безлічі сховищ даних, що полегшує проблеми переносимості. Ось тут можна знайти плутанину над тим, чи не модельний інтерфейс насправді є "контролером".

Взагалі кажучи, контролер пов'язує модель і погляд (які є м'ясо-картоплею програми.) У розробці какао це може бути спрощеним до того, що контролер обробляється через GUI 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.